"typenum",
]
-[[package]]
-name = "block-buffer"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
-dependencies = [
- "block-padding",
- "byte-tools",
- "byteorder",
- "generic-array 0.12.4",
-]
-
[[package]]
name = "block-buffer"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
dependencies = [
- "generic-array 0.14.4",
-]
-
-[[package]]
-name = "block-padding"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
-dependencies = [
- "byte-tools",
+ "generic-array",
]
[[package]]
"toml",
]
-[[package]]
-name = "byte-tools"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
-
[[package]]
name = "bytecount"
version = "0.6.2"
"packed_simd_2",
]
-[[package]]
-name = "byteorder"
-version = "1.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
-
[[package]]
name = "bytes"
version = "1.0.1"
[[package]]
name = "clap"
-version = "3.2.5"
+version = "3.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53da17d37dba964b9b3ecb5c5a1f193a2762c700e6829201e645b9381c99dc7"
+checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd"
dependencies = [
"atty",
"bitflags",
[[package]]
name = "clap_derive"
-version = "3.2.5"
+version = "3.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9"
+checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
dependencies = [
"heck",
"proc-macro-error",
[[package]]
name = "combine"
-version = "4.6.3"
+version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062"
+checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4"
dependencies = [
"bytes",
"memchr",
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06"
dependencies = [
- "generic-array 0.14.4",
+ "generic-array",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
-[[package]]
-name = "digest"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
-dependencies = [
- "generic-array 0.12.4",
-]
-
[[package]]
name = "digest"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837"
dependencies = [
- "block-buffer 0.10.2",
+ "block-buffer",
"crypto-common",
]
"once_cell",
]
-[[package]]
-name = "fake-simd"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
-
[[package]]
name = "fallible-iterator"
version = "0.2.0"
"termcolor",
]
-[[package]]
-name = "generic-array"
-version = "0.12.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
-dependencies = [
- "typenum",
-]
-
[[package]]
name = "generic-array"
version = "0.14.4"
[[package]]
name = "handlebars"
-version = "4.1.0"
+version = "4.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72a0ffab8c36d0436114310c7e10b59b3307e650ddfabf6d006028e29a70c6e6"
+checksum = "360d9740069b2f6cbb63ce2dbaa71a20d3185350cbb990d7bebeb9318415eb17"
dependencies = [
"log",
"pest",
"pest_derive",
- "quick-error 2.0.0",
"serde",
"serde_json",
+ "thiserror",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
- "quick-error 1.2.3",
+ "quick-error",
]
[[package]]
[[package]]
name = "im-rc"
-version = "15.0.0"
+version = "15.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f"
+checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
dependencies = [
"bitmaps",
- "rand_core 0.5.1",
- "rand_xoshiro 0.4.0",
+ "rand_core 0.6.2",
+ "rand_xoshiro",
"sized-chunks",
"typenum",
"version_check",
"rustc-std-workspace-core",
]
+[[package]]
+name = "libffi"
+version = "3.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e454b3efb16fba3b17810ae5e41df02b649e564ab3c5a34b3b93ed07ad287e6"
+dependencies = [
+ "libc",
+ "libffi-sys",
+]
+
+[[package]]
+name = "libffi-sys"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab4106b7f09d7b87d021334d5618fac1dfcfb824d4c5fe111ff0074dfd242e15"
+dependencies = [
+ "cc",
+]
+
[[package]]
name = "libgit2-sys"
version = "0.14.0+1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6a38fc55c8bbc10058782919516f88826e70320db6d206aebc49611d24216ae"
dependencies = [
- "digest 0.10.2",
+ "digest",
]
[[package]]
"getrandom 0.2.0",
"lazy_static",
"libc",
+ "libffi",
"libloading",
"log",
"measureme",
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
-[[package]]
-name = "opaque-debug"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
-
[[package]]
name = "opener"
version = "0.5.0"
[[package]]
name = "pest"
-version = "2.1.3"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
+checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4"
dependencies = [
+ "thiserror",
"ucd-trie",
]
[[package]]
name = "pest_derive"
-version = "2.1.0"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
+checksum = "905708f7f674518498c1f8d644481440f476d39ca6ecae83319bba7c6c12da91"
dependencies = [
"pest",
"pest_generator",
[[package]]
name = "pest_generator"
-version = "2.1.3"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
+checksum = "5803d8284a629cc999094ecd630f55e91b561a1d1ba75e233b00ae13b91a69ad"
dependencies = [
"pest",
"pest_meta",
[[package]]
name = "pest_meta"
-version = "2.1.3"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
+checksum = "1538eb784f07615c6d9a8ab061089c6c54a344c5b4301db51990ca1c241e8c04"
dependencies = [
- "maplit",
+ "once_cell",
"pest",
- "sha-1 0.8.2",
+ "sha-1",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
-[[package]]
-name = "quick-error"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ac73b1112776fc109b2e61909bc46c7e1bf0d7f690ffb1676553acce16d5cda"
-
[[package]]
name = "quine-mc_cluskey"
version = "0.2.4"
"rand_core 0.5.1",
]
-[[package]]
-name = "rand_xoshiro"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004"
-dependencies = [
- "rand_core 0.5.1",
-]
-
[[package]]
name = "rand_xoshiro"
version = "0.6.0"
"bstr",
"clap",
"libz-sys",
- "memchr",
"regex",
"serde_json",
"syn",
"rustc_macros",
"rustc_serialize",
"rustc_span",
+ "rustc_target",
"serde",
"serde_json",
"termcolor",
"gsgdt",
"polonius-engine",
"rand 0.8.5",
- "rand_xoshiro 0.6.0",
+ "rand_xoshiro",
"rustc-rayon",
"rustc-rayon-core",
"rustc_apfloat",
"rustc_macros",
"rustc_serialize",
"scoped-tls",
- "sha-1 0.10.0",
+ "sha-1",
"sha2",
"tracing",
"unicode-width",
dependencies = [
"itertools",
"rustc_data_structures",
+ "rustc_hir",
"rustc_infer",
"rustc_macros",
"rustc_middle",
"serde",
]
-[[package]]
-name = "sha-1"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
-dependencies = [
- "block-buffer 0.7.3",
- "digest 0.8.1",
- "fake-simd",
- "opaque-debug",
-]
-
[[package]]
name = "sha-1"
version = "0.10.0"
dependencies = [
"cfg-if 1.0.0",
"cpufeatures",
- "digest 0.10.2",
+ "digest",
]
[[package]]
dependencies = [
"cfg-if 1.0.0",
"cpufeatures",
- "digest 0.10.2",
+ "digest",
]
[[package]]
[[package]]
name = "thiserror"
-version = "1.0.30"
+version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
+checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.30"
+version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
+checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09"
dependencies = [
"proc-macro2",
"quote",
static_assert_size!(Fn, 192);
static_assert_size!(ForeignItem, 96);
static_assert_size!(ForeignItemKind, 24);
+ static_assert_size!(GenericArg, 24);
static_assert_size!(GenericBound, 88);
static_assert_size!(Generics, 72);
static_assert_size!(Impl, 200);
static_assert_size!(ItemKind, 112);
static_assert_size!(Lit, 48);
static_assert_size!(LitKind, 24);
+ static_assert_size!(Local, 72);
+ static_assert_size!(Param, 40);
static_assert_size!(Pat, 120);
static_assert_size!(PatKind, 96);
static_assert_size!(Path, 40);
let op = match *op {
InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In {
reg: lower_reg(reg),
- expr: self.lower_expr_mut(expr),
+ expr: self.lower_expr(expr),
},
InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out {
reg: lower_reg(reg),
late,
- expr: expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
+ expr: expr.as_ref().map(|expr| self.lower_expr(expr)),
},
InlineAsmOperand::InOut { reg, late, ref expr } => {
hir::InlineAsmOperand::InOut {
reg: lower_reg(reg),
late,
- expr: self.lower_expr_mut(expr),
+ expr: self.lower_expr(expr),
}
}
InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
hir::InlineAsmOperand::SplitInOut {
reg: lower_reg(reg),
late,
- in_expr: self.lower_expr_mut(in_expr),
- out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
+ in_expr: self.lower_expr(in_expr),
+ out_expr: out_expr.as_ref().map(|expr| self.lower_expr(expr)),
}
}
InlineAsmOperand::Const { ref anon_const } => {
ParenthesizedGenericArgs::Err,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
));
- let args = self.arena.alloc_from_iter(
- [&*receiver].into_iter().chain(args.iter()).map(|x| self.lower_expr_mut(x)),
- );
- hir::ExprKind::MethodCall(hir_seg, args, self.lower_span(span))
+ let receiver = self.lower_expr(receiver);
+ let args =
+ self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x)));
+ hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(span))
}
ExprKind::Binary(binop, ref lhs, ref rhs) => {
let binop = self.lower_binop(binop);
binding: hir::HirId,
attrs: AttrVec,
) -> hir::Expr<'hir> {
+ let hir_id = self.next_id();
+ let res = Res::Local(binding);
let expr_path = hir::ExprKind::Path(hir::QPath::Resolved(
None,
self.arena.alloc(hir::Path {
span: self.lower_span(span),
- res: Res::Local(binding),
- segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
+ res,
+ segments: arena_vec![self; hir::PathSegment::new(ident, hir_id, res)],
}),
));
}
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'hir PathSegment<'hir>) {
- if let Some(hir_id) = path_segment.hir_id {
- self.insert(path_span, hir_id, Node::PathSegment(path_segment));
- }
+ self.insert(path_span, path_segment.hir_id, Node::PathSegment(path_segment));
intravisit::walk_path_segment(self, path_span, path_segment);
}
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
allow_gen_future: Some([sym::gen_future][..].into()),
allow_into_future: Some([sym::into_future][..].into()),
+ generics_def_id_map: Default::default(),
};
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
self.with_lctx(CRATE_NODE_ID, |lctx| {
let module = lctx.lower_mod(&c.items, &c.spans);
lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
- hir::OwnerNode::Crate(lctx.arena.alloc(module))
+ hir::OwnerNode::Crate(module)
})
}
}
impl<'hir> LoweringContext<'_, 'hir> {
- pub(super) fn lower_mod(&mut self, items: &[P<Item>], spans: &ModSpans) -> hir::Mod<'hir> {
- hir::Mod {
+ pub(super) fn lower_mod(
+ &mut self,
+ items: &[P<Item>],
+ spans: &ModSpans,
+ ) -> &'hir hir::Mod<'hir> {
+ self.arena.alloc(hir::Mod {
spans: hir::ModSpans {
inner_span: self.lower_span(spans.inner_span),
inject_use_span: self.lower_span(spans.inject_use_span),
},
item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))),
- }
+ })
}
pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
params: &'hir [hir::Param<'hir>],
value: hir::Expr<'hir>,
) -> hir::BodyId {
- let body = hir::Body { generator_kind: self.generator_kind, params, value };
+ let body = hir::Body {
+ generator_kind: self.generator_kind,
+ params,
+ value: self.arena.alloc(value),
+ };
let id = body.id();
debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));
GenericParamKind::Const { .. } => None,
GenericParamKind::Type { .. } => {
let def_id = self.local_def_id(id).to_def_id();
+ let hir_id = self.next_id();
+ let res = Res::Def(DefKind::TyParam, def_id);
let ty_path = self.arena.alloc(hir::Path {
span: param_span,
- res: Res::Def(DefKind::TyParam, def_id),
- segments: self.arena.alloc_from_iter([hir::PathSegment::from_ident(ident)]),
+ res,
+ segments: self
+ .arena
+ .alloc_from_iter([hir::PathSegment::new(ident, hir_id, res)]),
});
let ty_id = self.next_id();
let bounded_ty =
allow_try_trait: Option<Lrc<[Symbol]>>,
allow_gen_future: Option<Lrc<[Symbol]>>,
allow_into_future: Option<Lrc<[Symbol]>>,
+
+ /// Mapping from generics `def_id`s to TAIT generics `def_id`s.
+ /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
+ /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
+ /// field from the original parameter 'a to the new parameter 'a1.
+ generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
}
trait ResolverAstLoweringExt {
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind;
- /// Record the map from `from` local def id to `to` local def id, on `generics_def_id_map`
- /// field.
- fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId);
- /// Get the previously recorded `to` local def id given the `from` local def id, obtained using
- /// `generics_def_id_map` field.
- fn get_remapped_def_id(&self, local_def_id: LocalDefId) -> LocalDefId;
}
impl ResolverAstLoweringExt for ResolverAstLowering {
fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind {
self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang)
}
-
- /// Push a remapping into the top-most map.
- /// Panics if no map has been pushed.
- /// Remapping is used when creating lowering `-> impl Trait` return
- /// types to create the resulting opaque type.
- #[instrument(level = "debug", skip(self))]
- fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId) {
- self.generics_def_id_map.last_mut().expect("no map pushed").insert(from, to);
- }
-
- fn get_remapped_def_id(&self, mut local_def_id: LocalDefId) -> LocalDefId {
- // `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we
- // push new mappings so we need to try first the latest mappings, hence `iter().rev()`.
- //
- // Consider:
- //
- // `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}`
- //
- // We would end with a generics_def_id_map like:
- //
- // `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]`
- //
- // for the opaque type generated on `impl Sized + 'b`, We want the result to be:
- // impl_sized#'b, so iterating forward is the wrong thing to do.
- for map in self.generics_def_id_map.iter().rev() {
- if let Some(r) = map.get(&local_def_id) {
- debug!("def_id_remapper: remapping from `{local_def_id:?}` to `{r:?}`");
- local_def_id = *r;
- } else {
- debug!("def_id_remapper: no remapping for `{local_def_id:?}` found in map");
- }
- }
-
- local_def_id
- }
}
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
self.resolver
.node_id_to_def_id
.get(&node)
- .map(|local_def_id| self.resolver.get_remapped_def_id(*local_def_id))
+ .map(|local_def_id| self.get_remapped_def_id(*local_def_id))
}
fn local_def_id(&self, node: NodeId) -> LocalDefId {
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node))
}
+ /// Get the previously recorded `to` local def id given the `from` local def id, obtained using
+ /// `generics_def_id_map` field.
+ fn get_remapped_def_id(&self, mut local_def_id: LocalDefId) -> LocalDefId {
+ // `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we
+ // push new mappings so we need to try first the latest mappings, hence `iter().rev()`.
+ //
+ // Consider:
+ //
+ // `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}`
+ //
+ // We would end with a generics_def_id_map like:
+ //
+ // `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]`
+ //
+ // for the opaque type generated on `impl Sized + 'b`, We want the result to be:
+ // impl_sized#'b, so iterating forward is the wrong thing to do.
+ for map in self.generics_def_id_map.iter().rev() {
+ if let Some(r) = map.get(&local_def_id) {
+ debug!("def_id_remapper: remapping from `{local_def_id:?}` to `{r:?}`");
+ local_def_id = *r;
+ } else {
+ debug!("def_id_remapper: no remapping for `{local_def_id:?}` found in map");
+ }
+ }
+
+ local_def_id
+ }
+
/// Freshen the `LoweringContext` and ready it to lower a nested item.
/// The lowered item is registered into `self.children`.
///
remap: FxHashMap<LocalDefId, LocalDefId>,
f: impl FnOnce(&mut Self) -> R,
) -> R {
- self.resolver.generics_def_id_map.push(remap);
+ self.generics_def_id_map.push(remap);
let res = f(self);
- self.resolver.generics_def_id_map.pop();
+ self.generics_def_id_map.pop();
res
}
}
_ => {}
}
- GenericArg::Type(self.lower_ty_direct(&ty, itctx))
+ GenericArg::Type(self.lower_ty(&ty, itctx))
}
ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg {
value: self.lower_anon_const(&ct),
return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx);
}
TyKind::ImplicitSelf => {
+ let hir_id = self.lower_node_id(t.id);
let res = self.expect_full_res(t.id);
let res = self.lower_res(res);
hir::TyKind::Path(hir::QPath::Resolved(
None,
self.arena.alloc(hir::Path {
res,
- segments: arena_vec![self; hir::PathSegment::from_ident(
- Ident::with_dummy_span(kw::SelfUpper)
+ segments: arena_vec![self; hir::PathSegment::new(
+ Ident::with_dummy_span(kw::SelfUpper),
+ hir_id,
+ res
)],
span: self.lower_span(t.span),
}),
let name = match res {
LifetimeRes::Param { param, .. } => {
let p_name = ParamName::Plain(ident);
- let param = self.resolver.get_remapped_def_id(param);
+ let param = self.get_remapped_def_id(param);
hir::LifetimeName::Param(param, p_name)
}
hir::PredicateOrigin::ImplTrait,
);
+ let hir_id = self.next_id();
+ let res = Res::Def(DefKind::TyParam, def_id.to_def_id());
let ty = hir::TyKind::Path(hir::QPath::Resolved(
None,
self.arena.alloc(hir::Path {
span: self.lower_span(span),
- res: Res::Def(DefKind::TyParam, def_id.to_def_id()),
- segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))],
+ res,
+ segments:
+ arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)],
}),
));
lower_sub(self),
)
}
- Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
- None,
- self.arena.alloc(hir::Path {
- span: self.lower_span(ident.span),
- res: self.lower_res(res),
- segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))],
- }),
- )),
+ Some(res) => {
+ let hir_id = self.next_id();
+ let res = self.lower_res(res);
+ hir::PatKind::Path(hir::QPath::Resolved(
+ None,
+ self.arena.alloc(hir::Path {
+ span: self.lower_span(ident.span),
+ res,
+ segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)],
+ }),
+ ))
+ }
}
}
}
let res = self.expect_full_res(segment.id);
- let id = self.lower_node_id(segment.id);
+ let hir_id = self.lower_node_id(segment.id);
debug!(
"lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
- segment.ident, segment.id, id,
+ segment.ident, segment.id, hir_id,
);
hir::PathSegment {
ident: self.lower_ident(segment.ident),
- hir_id: Some(id),
- res: Some(self.lower_res(res)),
+ hir_id,
+ res: self.lower_res(res),
infer_args,
args: if generic_args.is_empty() && generic_args.span.is_empty() {
None
}
FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
};
- let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))];
+ let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))];
let binding = self.output_ty_binding(output_ty.span, output_ty);
(
GenericArgsCtor {
ast::ItemKind::GlobalAsm(ref asm) => {
self.head(visibility_qualified(&item.vis, "global_asm!"));
self.print_inline_asm(asm);
+ self.word(";");
+ self.end();
self.end();
}
ast::ItemKind::TyAlias(box ast::TyAlias {
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
+/// The version placeholder that recently stabilized features contain inside the
+/// `since` field of the `#[stable]` attribute.
+///
+/// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591).
+pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
+
pub fn is_builtin_attr(attr: &Attribute) -> bool {
attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
}
}
}
+ if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER {
+ let version = option_env!("CFG_VERSION").unwrap_or("<current>");
+ let version = version.split(' ').next().unwrap();
+ since = Some(Symbol::intern(&version));
+ }
+
match (feature, since) {
(Some(feature), Some(since)) => {
let level = Stable { since, allowed_through_unstable_modules: false };
let ty = place.ty(self.body, self.infcx.tcx).ty;
// If we're in pattern, we do nothing in favor of the previous suggestion (#80913).
- if is_loop_move & !in_pattern {
+ // Same for if we're in a loop, see #101119.
+ if is_loop_move & !in_pattern && !matches!(use_spans, UseSpans::ClosureUse { .. }) {
if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
// We have a `&mut` ref, we need to reborrow on each iteration (#62112).
err.span_suggestion_verbose(
Applicability::MachineApplicable,
);
self.suggested = true;
- } else if let hir::ExprKind::MethodCall(_path, args @ [_, ..], sp) = expr.kind
- && let hir::ExprKind::Index(val, index) = args[0].kind
+ } else if let hir::ExprKind::MethodCall(_path, receiver, _, sp) = expr.kind
+ && let hir::ExprKind::Index(val, index) = receiver.kind
&& expr.span == self.assign_span
{
// val[index].path(args..);
".get_mut(".to_string(),
),
(
- index.span.shrink_to_hi().with_hi(args[0].span.hi()),
+ index.span.shrink_to_hi().with_hi(receiver.span.hi()),
").map(|val| val".to_string(),
),
(sp.shrink_to_hi(), ")".to_string()),
[
Expr {
kind:
- MethodCall(
- path_segment,
- _args,
- span,
- ),
+ MethodCall(path_segment, _, _, span),
hir_id,
..
},
_,
) = hir_map.body(fn_body_id).value.kind
{
- let opt_suggestions = path_segment
- .hir_id
- .map(|path_hir_id| self.infcx.tcx.typeck(path_hir_id.owner))
- .and_then(|typeck| typeck.type_dependent_def_id(*hir_id))
+ let opt_suggestions = self
+ .infcx
+ .tcx
+ .typeck(path_segment.hir_id.owner)
+ .type_dependent_def_id(*hir_id)
.and_then(|def_id| self.infcx.tcx.impl_of_method(def_id))
.map(|def_id| self.infcx.tcx.associated_items(def_id))
.map(|assoc_items| {
let mut closure_span = None::<rustc_span::Span>;
match expr.kind {
hir::ExprKind::MethodCall(.., args, _) => {
- // only the first closre parameter of the method. args[0] is MethodCall PathSegment
- for i in 1..args.len() {
+ for arg in args {
if let hir::ExprKind::Closure(hir::Closure {
capture_clause: hir::CaptureBy::Ref,
..
- }) = args[i].kind
+ }) = arg.kind
{
- closure_span = Some(args[i].span.shrink_to_lo());
+ closure_span = Some(arg.span.shrink_to_lo());
break;
}
}
use rustc_hir::LangItem;
use rustc_middle::ty::subst::GenericArg;
use rustc_middle::ty::AssocKind;
-use rustc_session::config::EntryFnType;
+use rustc_session::config::{sigpipe, EntryFnType};
use rustc_span::symbol::Ident;
use crate::prelude::*;
is_jit: bool,
is_primary_cgu: bool,
) {
- let (main_def_id, is_main_fn) = match tcx.entry_fn(()) {
+ let (main_def_id, (is_main_fn, sigpipe)) = match tcx.entry_fn(()) {
Some((def_id, entry_ty)) => (
def_id,
match entry_ty {
- EntryFnType::Main => true,
- EntryFnType::Start => false,
+ EntryFnType::Main { sigpipe } => (true, sigpipe),
+ EntryFnType::Start => (false, sigpipe::DEFAULT),
},
),
None => return,
return;
}
- create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn);
+ create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn, sigpipe);
fn create_entry_fn(
tcx: TyCtxt<'_>,
rust_main_def_id: DefId,
ignore_lang_start_wrapper: bool,
is_main_fn: bool,
+ sigpipe: u8,
) {
let main_ret_ty = tcx.fn_sig(rust_main_def_id).output();
// Given that `main()` has no arguments,
bcx.switch_to_block(block);
let arg_argc = bcx.append_block_param(block, m.target_config().pointer_type());
let arg_argv = bcx.append_block_param(block, m.target_config().pointer_type());
+ let arg_sigpipe = bcx.ins().iconst(types::I8, sigpipe as i64);
let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func);
let main_val = bcx.ins().func_addr(m.target_config().pointer_type(), main_func_ref);
let func_ref = m.declare_func_in_func(start_func_id, &mut bcx.func);
- let call_inst = bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv]);
+ let call_inst =
+ bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv, arg_sigpipe]);
bcx.inst_results(call_inst)[0]
} else {
// using user-defined start fn
if let LinkerFlavor::Gcc = flavor {
match ld_impl {
LdImpl::Lld => {
- let tools_path = sess.get_tools_search_paths(false);
- let gcc_ld_dir = tools_path
- .into_iter()
- .map(|p| p.join("gcc-ld"))
- .find(|p| {
- p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }).exists()
- })
- .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found"));
- cmd.arg({
- let mut arg = OsString::from("-B");
- arg.push(gcc_ld_dir);
- arg
- });
- cmd.arg(format!("-Wl,-rustc-lld-flavor={}", sess.target.lld_flavor.as_str()));
+ // Implement the "self-contained" part of -Zgcc-ld
+ // by adding rustc distribution directories to the tool search path.
+ for path in sess.get_tools_search_paths(false) {
+ cmd.arg({
+ let mut arg = OsString::from("-B");
+ arg.push(path.join("gcc-ld"));
+ arg
+ });
+ }
+ // Implement the "linker flavor" part of -Zgcc-ld
+ // by asking cc to use some kind of lld.
+ cmd.arg("-fuse-ld=lld");
+ if sess.target.lld_flavor != LldFlavor::Ld {
+ // Tell clang to use a non-default LLD flavor.
+ // Gcc doesn't understand the target option, but we currently assume
+ // that gcc is not used for Apple and Wasm targets (#97402).
+ cmd.arg(format!("--target={}", sess.target.llvm_target));
+ }
}
}
} else {
let main_llfn = cx.get_fn_addr(instance);
- let use_start_lang_item = EntryFnType::Start != entry_type;
- let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, use_start_lang_item);
+ let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, entry_type);
return Some(entry_fn);
fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx,
rust_main: Bx::Value,
rust_main_def_id: DefId,
- use_start_lang_item: bool,
+ entry_type: EntryFnType,
) -> Bx::Function {
// The entry function is either `int main(void)` or `int main(int argc, char **argv)`,
// depending on whether the target needs `argc` and `argv` to be passed in.
let i8pp_ty = cx.type_ptr_to(cx.type_i8p());
let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx);
- let (start_fn, start_ty, args) = if use_start_lang_item {
+ let (start_fn, start_ty, args) = if let EntryFnType::Main { sigpipe } = entry_type {
let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None);
let start_fn = cx.get_fn_addr(
ty::Instance::resolve(
.unwrap()
.unwrap(),
);
- let start_ty = cx.type_func(&[cx.val_ty(rust_main), isize_ty, i8pp_ty], isize_ty);
- (start_fn, start_ty, vec![rust_main, arg_argc, arg_argv])
+
+ let i8_ty = cx.type_i8();
+ let arg_sigpipe = bx.const_u8(sigpipe);
+
+ let start_ty =
+ cx.type_func(&[cx.val_ty(rust_main), isize_ty, i8pp_ty, i8_ty], isize_ty);
+ (start_fn, start_ty, vec![rust_main, arg_argc, arg_argv, arg_sigpipe])
} else {
debug!("using user-defined start fn");
let start_ty = cx.type_func(&[isize_ty, i8pp_ty], isize_ty);
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::lang_items::LangItem;
use rustc_index::vec::Idx;
-use rustc_middle::mir::AssertKind;
-use rustc_middle::mir::{self, SwitchTargets};
+use rustc_middle::mir::{self, AssertKind, SwitchTargets};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty, TypeVisitable};
// All `#[rustc_do_not_const_check]` functions should be hooked here.
let def_id = instance.def_id();
- if Some(def_id) == self.tcx.lang_items().const_eval_select() {
- // redirect to const_eval_select_ct
- if let Some(const_eval_select) = self.tcx.lang_items().const_eval_select_ct() {
- return Ok(Some(
- ty::Instance::resolve(
- *self.tcx,
- ty::ParamEnv::reveal_all(),
- const_eval_select,
- instance.substs,
- )
- .unwrap()
- .unwrap(),
- ));
- }
- } else if Some(def_id) == self.tcx.lang_items().panic_display()
+ if Some(def_id) == self.tcx.lang_items().panic_display()
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
{
// &str or &&str
use std::fmt::Debug;
use std::hash::Hash;
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_middle::mir;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::DefId;
kind: Option<MemoryKind<Self::MemoryKind>>,
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra>>>;
+ fn eval_inline_asm(
+ _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+ _template: &'tcx [InlineAsmTemplatePiece],
+ _operands: &[mir::InlineAsmOperand<'tcx>],
+ _options: InlineAsmOptions,
+ ) -> InterpResult<'tcx> {
+ throw_unsup_format!("inline assembly is not supported")
+ }
+
/// Hook for performing extra checks on a memory read access.
///
/// Takes read-only access to the allocation so we can keep all the memory read
use std::borrow::Cow;
+use rustc_ast::ast::InlineAsmOptions;
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
use rustc_middle::ty::Instance;
use rustc_middle::{
terminator.kind
),
- // Inline assembly can't be interpreted.
- InlineAsm { .. } => throw_unsup_format!("inline assembly is not supported"),
+ InlineAsm { template, ref operands, options, destination, .. } => {
+ M::eval_inline_asm(self, template, operands, options)?;
+ if options.contains(InlineAsmOptions::NORETURN) {
+ throw_ub_format!("returned from noreturn inline assembly");
+ }
+ self.go_to_block(
+ destination
+ .expect("InlineAsm terminators without noreturn must have a destination"),
+ )
+ }
}
Ok(())
//! to be const-safe.
use std::convert::TryFrom;
-use std::fmt::Write;
+use std::fmt::{Display, Write};
use std::num::NonZeroUsize;
use rustc_ast::Mutability;
fn read_immediate(
&self,
op: &OpTy<'tcx, M::Provenance>,
- expected: &str,
+ expected: impl Display,
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
Ok(try_validation!(
self.ecx.read_immediate(op),
fn read_scalar(
&self,
op: &OpTy<'tcx, M::Provenance>,
- expected: &str,
+ expected: impl Display,
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
Ok(self.read_immediate(op, expected)?.to_scalar())
}
value: &OpTy<'tcx, M::Provenance>,
kind: &str,
) -> InterpResult<'tcx> {
- let place = self.ecx.ref_to_mplace(&self.read_immediate(value, &format!("a {kind}"))?)?;
+ let place =
+ self.ecx.ref_to_mplace(&self.read_immediate(value, format_args!("a {kind}"))?)?;
// Handle wide pointers.
// Check metadata early, for better diagnostics
if place.layout.is_unsized() {
if (src, dest).has_opaque_types() {
return true;
}
- // Normalize projections and things like that.
- let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
- let src = self.tcx.normalize_erasing_regions(param_env, src);
- let dest = self.tcx.normalize_erasing_regions(param_env, dest);
+ // Normalize projections and things like that.
// Type-changing assignments can happen when subtyping is used. While
// all normal lifetimes are erased, higher-ranked types with their
// late-bound lifetimes are still around and can lead to type
// differences. So we compare ignoring lifetimes.
- equal_up_to_regions(self.tcx, param_env, src, dest)
+
+ // First, try with reveal_all. This might not work in some cases, as the predicates
+ // can be cleared in reveal_all mode. We try the reveal first anyways as it is used
+ // by some other passes like inlining as well.
+ let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
+ if equal_up_to_regions(self.tcx, param_env, src, dest) {
+ return true;
+ }
+
+ // If this fails, we can try it without the reveal.
+ equal_up_to_regions(self.tcx, self.param_env, src, dest)
}
}
.suggestion = consider restricting its visibility
.help = or consider exporting it for use by other crates
+lint_builtin_unexpected_cli_config_name = unexpected `{$name}` as condition name
+ .help = was set with `--cfg` but isn't in the `--check-cfg` expected names
+
+lint_builtin_unexpected_cli_config_value = unexpected condition value `{$value}` for condition name `{$name}`
+ .help = was set with `--cfg` but isn't in the `--check-cfg` expected values
+
lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases
--- /dev/null
+metadata_rlib_required =
+ crate `{$crate_name}` required to be available in rlib format, but was not found in this form
+
+metadata_lib_required =
+ crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
+
+metadata_crate_dep_multiple =
+ cannot satisfy dependencies so `{$crate_name}` only shows up once
+ .help = having upstream crates all available in one format will likely make this go away
+
+metadata_two_panic_runtimes =
+ cannot link together two panic runtimes: {$prev_name} and {$cur_name}
+
+metadata_bad_panic_strategy =
+ the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`
+
+metadata_required_panic_strategy =
+ the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+
+metadata_incompatible_panic_in_drop_strategy =
+ the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+
+metadata_multiple_names_in_link =
+ multiple `name` arguments in a single `#[link]` attribute
+
+metadata_multiple_kinds_in_link =
+ multiple `kind` arguments in a single `#[link]` attribute
+
+metadata_link_name_form =
+ link name must be of the form `name = "string"`
+
+metadata_link_kind_form =
+ link kind must be of the form `kind = "string"`
+
+metadata_link_modifiers_form =
+ link modifiers must be of the form `modifiers = "string"`
+
+metadata_link_cfg_form =
+ link cfg must be of the form `cfg(/* predicate */)`
+
+metadata_wasm_import_form =
+ wasm import module must be of the form `wasm_import_module = "string"`
+
+metadata_empty_link_name =
+ link name must not be empty
+ .label = empty link name
+
+metadata_link_framework_apple =
+ link kind `framework` is only supported on Apple targets
+
+metadata_framework_only_windows =
+ link kind `raw-dylib` is only supported on Windows targets
+
+metadata_unknown_link_kind =
+ unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib
+ .label = unknown link kind
+
+metadata_multiple_link_modifiers =
+ multiple `modifiers` arguments in a single `#[link]` attribute
+
+metadata_multiple_cfgs =
+ multiple `cfg` arguments in a single `#[link]` attribute
+
+metadata_link_cfg_single_predicate =
+ link cfg must have a single predicate argument
+
+metadata_multiple_wasm_import =
+ multiple `wasm_import_module` arguments in a single `#[link]` attribute
+
+metadata_unexpected_link_arg =
+ unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
+
+metadata_invalid_link_modifier =
+ invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
+
+metadata_multiple_modifiers =
+ multiple `{$modifier}` modifiers in a single `modifiers` argument
+
+metadata_bundle_needs_static =
+ linking modifier `bundle` is only compatible with `static` linking kind
+
+metadata_whole_archive_needs_static =
+ linking modifier `whole-archive` is only compatible with `static` linking kind
+
+metadata_as_needed_compatibility =
+ linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
+
+metadata_unknown_link_modifier =
+ unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
+
+metadata_incompatible_wasm_link =
+ `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
+
+metadata_link_requires_name =
+ `#[link]` attribute requires a `name = "string"` argument
+ .label = missing `name` argument
+
+metadata_raw_dylib_no_nul =
+ link name must not contain NUL characters if link kind is `raw-dylib`
+
+metadata_link_ordinal_raw_dylib =
+ `#[link_ordinal]` is only supported if link kind is `raw-dylib`
+
+metadata_lib_framework_apple =
+ library kind `framework` is only supported on Apple targets
+
+metadata_empty_renaming_target =
+ an empty renaming target was specified for library `{$lib_name}`
+
+metadata_renaming_no_link =
+ renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
+
+metadata_multiple_renamings =
+ multiple renamings were specified for library `{$lib_name}`
+
+metadata_no_link_mod_override =
+ overriding linking modifiers from command line is not supported
+
+metadata_unsupported_abi_i686 =
+ ABI not supported by `#[link(kind = "raw-dylib")]` on i686
+
+metadata_unsupported_abi =
+ ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+
+metadata_fail_create_file_encoder =
+ failed to create file encoder: {$err}
+
+metadata_fail_seek_file =
+ failed to seek the file: {$err}
+
+metadata_fail_write_file =
+ failed to write to the file: {$err}
+
+metadata_crate_not_panic_runtime =
+ the crate `{$crate_name}` is not a panic runtime
+
+metadata_no_panic_strategy =
+ the crate `{$crate_name}` does not have the panic strategy `{$strategy}`
+
+metadata_profiler_builtins_needs_core =
+ `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
+
+metadata_not_profiler_runtime =
+ the crate `{$crate_name}` is not a profiler runtime
+
+metadata_no_multiple_global_alloc =
+ cannot define multiple global allocators
+ .label = cannot define a new global allocator
+
+metadata_prev_global_alloc =
+ previous global allocator defined here
+
+metadata_conflicting_global_alloc =
+ the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}
+
+metadata_global_alloc_required =
+ no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
+
+metadata_no_transitive_needs_dep =
+ the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`
+
+metadata_failed_write_error =
+ failed to write {$filename}: {$err}
+
+metadata_failed_create_tempdir =
+ couldn't create a temp dir: {$err}
+
+metadata_failed_create_file =
+ failed to create the file {$filename}: {$err}
+
+metadata_failed_create_encoded_metadata =
+ failed to create encoded metadata from file: {$err}
+
+metadata_non_ascii_name =
+ cannot load a crate with a non-ascii name `{$crate_name}`
+
+metadata_extern_location_not_exist =
+ extern location for {$crate_name} does not exist: {$location}
+
+metadata_extern_location_not_file =
+ extern location for {$crate_name} is not a file: {$location}
+
+metadata_multiple_candidates =
+ multiple {$flavor} candidates for `{$crate_name}` found
+
+metadata_multiple_matching_crates =
+ multiple matching crates for `{$crate_name}`
+ .note = candidates:{$candidates}
+
+metadata_symbol_conflicts_current =
+ the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two.
+
+metadata_symbol_conflicts_others =
+ found two different crates with name `{$crate_name}` that are not distinguished by differing `-C metadata`. This will result in symbol conflicts between the two.
+
+metadata_stable_crate_id_collision =
+ found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values.
+
+metadata_dl_error =
+ {$err}
+
+metadata_newer_crate_version =
+ found possibly newer version of crate `{$crate_name}`{$add_info}
+ .note = perhaps that crate needs to be recompiled?
+
+metadata_found_crate_versions =
+ the following crate versions were found:{$found_crates}
+
+metadata_no_crate_with_triple =
+ couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}
+
+metadata_found_staticlib =
+ found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}
+ .help = please recompile that crate using --crate-type lib
+
+metadata_incompatible_rustc =
+ found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info}
+ .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first)
+
+metadata_invalid_meta_files =
+ found invalid metadata files for crate `{$crate_name}`{$add_info}
+
+metadata_cannot_find_crate =
+ can't find crate for `{$crate_name}`{$add_info}
+
+metadata_no_dylib_plugin =
+ plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
+
+metadata_target_not_installed =
+ the `{$locator_triple}` target may not be installed
+
+metadata_target_no_std_support =
+ the `{$locator_triple}` target may not support the standard library
+
+metadata_consider_downloading_target =
+ consider downloading the target with `rustup target add {$locator_triple}`
+
+metadata_std_required =
+ `std` is required by `{$current_crate}` because it does not declare `#![no_std]`
+
+metadata_consider_building_std =
+ consider building the standard library from source with `cargo build -Zbuild-std`
+
+metadata_compiler_missing_profiler =
+ the compiler may have been built without the profiler runtime
+
+metadata_install_missing_components =
+ maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
+
+metadata_cant_find_crate =
+ can't find crate
+
+metadata_crate_location_unknown_type =
+ extern location for {$crate_name} is of an unknown type: {$path}
+
+metadata_lib_filename_form =
+ file name should be lib*.rlib or {dll_prefix}*.{dll_suffix}
+
+metadata_multiple_import_name_type =
+ multiple `import_name_type` arguments in a single `#[link]` attribute
+
+metadata_import_name_type_form =
+ import name type must be of the form `import_name_type = "string"`
+
+metadata_import_name_type_x86 =
+ import name type is only supported on x86
+
+metadata_unknown_import_name_type =
+ unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated
+
+metadata_import_name_type_raw =
+ import name type can only be used with link kind `raw-dylib`
--- /dev/null
+trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
+
+trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
+
+trait_selection_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
+ .label = deref recursion limit reached
+ .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
+ .label = empty on-clause here
+
+trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]`
+ .label = invalid on-clause here
+
+trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value
+ .label = expected value here
+ .note = eg `#[rustc_on_unimplemented(message="foo")]`
+
+trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc ->
+ [none] {""}
+ *[default] {" "}for type `{$self_desc}`
+ }:
+ .negative_implementation_here = negative implementation here
+ .negative_implementation_in_crate = negative implementation in crate `{$negative_impl_cname}`
+ .positive_implementation_here = positive implementation here
+ .positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}`
infer => "../locales/en-US/infer.ftl",
lint => "../locales/en-US/lint.ftl",
monomorphize => "../locales/en-US/monomorphize.ftl",
+ metadata => "../locales/en-US/metadata.ftl",
parser => "../locales/en-US/parser.ftl",
passes => "../locales/en-US/passes.ftl",
plugin_impl => "../locales/en-US/plugin_impl.ftl",
privacy => "../locales/en-US/privacy.ftl",
query_system => "../locales/en-US/query_system.ftl",
+ trait_selection => "../locales/en-US/trait_selection.ftl",
save_analysis => "../locales/en-US/save_analysis.ftl",
ty_utils => "../locales/en-US/ty_utils.ftl",
typeck => "../locales/en-US/typeck.ftl",
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_hir = { path = "../rustc_hir" }
rustc_lint_defs = { path = "../rustc_lint_defs" }
+rustc_target = { path = "../rustc_target" }
unicode-width = "0.1.4"
atty = "0.2"
termcolor = "1.0"
annotate-snippets = "0.9"
termize = "0.1.1"
-serde = { version = "1.0.125", features = ["derive"] }
+serde = { version = "1.0.125", features = [ "derive" ] }
serde_json = "1.0.59"
[target.'cfg(windows)'.dependencies]
-winapi = { version = "0.3", features = ["handleapi", "synchapi", "winbase"] }
+winapi = { version = "0.3", features = [ "handleapi", "synchapi", "winbase" ] }
use rustc_span::edition::LATEST_STABLE_EDITION;
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
use rustc_span::{edition::Edition, Span, DUMMY_SP};
+use rustc_target::spec::PanicStrategy;
use std::borrow::Cow;
use std::fmt;
use std::hash::{Hash, Hasher};
}
}
+impl IntoDiagnosticArg for PanicStrategy {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string()))
+ }
+}
+
impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {
fn into(self) -> FluentValue<'source> {
match self {
/// Allows creation of instances of a struct by moving fields that have
/// not changed from prior instances of the same struct (RFC #2528)
(active, type_changing_struct_update, "1.58.0", Some(86555), None),
+ /// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE.
+ (active, unix_sigpipe, "CURRENT_RUSTC_VERSION", Some(97889), None),
/// Allows unsized fn parameters.
(active, unsized_fn_params, "1.49.0", Some(48055), None),
/// Allows unsized rvalues at arguments and parameters.
),
// Entry point:
+ gated!(unix_sigpipe, Normal, template!(Word, NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, experimental!(unix_sigpipe)),
ungated!(start, Normal, template!(Word), WarnFollowing),
ungated!(no_start, CrateLevel, template!(Word), WarnFollowing),
ungated!(no_main, CrateLevel, template!(Word), WarnFollowing),
///
/// **Belongs to the type namespace.**
PrimTy(hir::PrimTy),
+
/// The `Self` type, optionally with the [`DefId`] of the trait it belongs to and
/// optionally with the [`DefId`] of the item introducing the `Self` type alias.
///
/// const fn baz<T>() -> usize { 10 }
/// ```
/// We do however allow `Self` in repeat expression even if it is generic to not break code
- /// which already works on stable while causing the `const_evaluatable_unchecked` future compat lint:
+ /// which already works on stable while causing the `const_evaluatable_unchecked` future compat
+ /// lint:
/// ```
/// fn foo<T>() {
/// let _bar = [1_u8; std::mem::size_of::<*mut T>()];
/// from mentioning generics (i.e. when used in an anonymous constant).
alias_to: Option<(DefId, bool)>,
},
+
/// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`.
///
/// **Belongs to the type namespace.**
///
/// *See also [`Res::SelfTy`].*
SelfCtor(DefId),
+
/// A local variable or function parameter.
///
/// **Belongs to the value namespace.**
pub struct PathSegment<'hir> {
/// The identifier portion of this path segment.
pub ident: Ident,
- // `id` and `res` are optional. We currently only use these in save-analysis,
- // any path segments without these will not have save-analysis info and
- // therefore will not have 'jump to def' in IDEs, but otherwise will not be
- // affected. (In general, we don't bother to get the defs for synthesized
- // segments, only for segments which have come from the AST).
- pub hir_id: Option<HirId>,
- pub res: Option<Res>,
+ pub hir_id: HirId,
+ pub res: Res,
/// Type/lifetime parameters attached to this path. They come in
/// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
impl<'hir> PathSegment<'hir> {
/// Converts an identifier to the corresponding segment.
- pub fn from_ident(ident: Ident) -> PathSegment<'hir> {
- PathSegment { ident, hir_id: None, res: None, infer_args: true, args: None }
+ pub fn new(ident: Ident, hir_id: HirId, res: Res) -> PathSegment<'hir> {
+ PathSegment { ident, hir_id, res, infer_args: true, args: None }
}
pub fn invalid() -> Self {
- Self::from_ident(Ident::empty())
+ Self::new(Ident::empty(), HirId::INVALID, Res::Err)
}
pub fn args(&self) -> &GenericArgs<'hir> {
#[derive(Debug, HashStable_Generic)]
pub enum GenericArg<'hir> {
Lifetime(Lifetime),
- Type(Ty<'hir>),
+ Type(&'hir Ty<'hir>),
Const(ConstArg),
Infer(InferArg),
}
}
}
- pub fn id(&self) -> HirId {
+ pub fn hir_id(&self) -> HirId {
match self {
GenericArg::Lifetime(l) => l.hir_id,
GenericArg::Type(t) => t.hir_id,
Semi(&'hir Expr<'hir>),
}
-/// Represents a `let` statement (i.e., `let <pat>:<ty> = <expr>;`).
+/// Represents a `let` statement (i.e., `let <pat>:<ty> = <init>;`).
#[derive(Debug, HashStable_Generic)]
pub struct Local<'hir> {
pub pat: &'hir Pat<'hir>,
#[derive(Debug, HashStable_Generic)]
pub struct Body<'hir> {
pub params: &'hir [Param<'hir>],
- pub value: Expr<'hir>,
+ pub value: &'hir Expr<'hir>,
pub generator_kind: Option<GeneratorKind>,
}
///
/// The `PathSegment` represents the method name and its generic arguments
/// (within the angle brackets).
- /// The first element of the `&[Expr]` is the expression that evaluates
+ /// The `&Expr` is the expression that evaluates
/// to the object on which the method is being called on (the receiver),
- /// and the remaining elements are the rest of the arguments.
+ /// and the `&[Expr]` is the rest of the arguments.
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
- /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d], span)`.
+ /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, x, [a, b, c, d], span)`.
/// The final `Span` represents the span of the function and arguments
/// (e.g. `foo::<Bar, Baz>(a, b, c, d)` in `x.foo::<Bar, Baz>(a, b, c, d)`
///
/// the `hir_id` of the `MethodCall` node itself.
///
/// [`type_dependent_def_id`]: ../../rustc_middle/ty/struct.TypeckResults.html#method.type_dependent_def_id
- MethodCall(&'hir PathSegment<'hir>, &'hir [Expr<'hir>], Span),
+ MethodCall(&'hir PathSegment<'hir>, &'hir Expr<'hir>, &'hir [Expr<'hir>], Span),
/// A tuple (e.g., `(a, b, c, d)`).
Tup(&'hir [Expr<'hir>]),
/// A binary operation (e.g., `a + b`, `a * b`).
pub enum InlineAsmOperand<'hir> {
In {
reg: InlineAsmRegOrRegClass,
- expr: Expr<'hir>,
+ expr: &'hir Expr<'hir>,
},
Out {
reg: InlineAsmRegOrRegClass,
late: bool,
- expr: Option<Expr<'hir>>,
+ expr: Option<&'hir Expr<'hir>>,
},
InOut {
reg: InlineAsmRegOrRegClass,
late: bool,
- expr: Expr<'hir>,
+ expr: &'hir Expr<'hir>,
},
SplitInOut {
reg: InlineAsmRegOrRegClass,
late: bool,
- in_expr: Expr<'hir>,
- out_expr: Option<Expr<'hir>>,
+ in_expr: &'hir Expr<'hir>,
+ out_expr: Option<&'hir Expr<'hir>>,
},
Const {
anon_const: AnonConst,
/// A MBE macro definition (`macro_rules!` or `macro`).
Macro(ast::MacroDef, MacroKind),
/// A module.
- Mod(Mod<'hir>),
+ Mod(&'hir Mod<'hir>),
/// An external module, e.g. `extern { .. }`.
ForeignMod { abi: Abi, items: &'hir [ForeignItemRef] },
/// Module-level inline assembly (from `global_asm!`).
mod size_asserts {
use super::*;
// These are in alphabetical order, which is easy to maintain.
- static_assert_size!(Block<'static>, 48);
- static_assert_size!(Expr<'static>, 56);
- static_assert_size!(ForeignItem<'static>, 72);
+ static_assert_size!(Block<'_>, 48);
+ static_assert_size!(Body<'_>, 32);
+ static_assert_size!(Expr<'_>, 64);
+ static_assert_size!(ExprKind<'_>, 48);
+ static_assert_size!(FnDecl<'_>, 40);
+ static_assert_size!(ForeignItem<'_>, 72);
+ static_assert_size!(ForeignItemKind<'_>, 40);
+ static_assert_size!(GenericArg<'_>, 40);
static_assert_size!(GenericBound<'_>, 48);
- static_assert_size!(Generics<'static>, 56);
- static_assert_size!(ImplItem<'static>, 88);
- static_assert_size!(Impl<'static>, 80);
- static_assert_size!(Item<'static>, 80);
- static_assert_size!(Pat<'static>, 88);
- static_assert_size!(QPath<'static>, 24);
- static_assert_size!(TraitItem<'static>, 96);
- static_assert_size!(Ty<'static>, 72);
+ static_assert_size!(Generics<'_>, 56);
+ static_assert_size!(Impl<'_>, 80);
+ static_assert_size!(ImplItem<'_>, 88);
+ static_assert_size!(ImplItemKind<'_>, 40);
+ static_assert_size!(Item<'_>, 80);
+ static_assert_size!(ItemKind<'_>, 48);
+ static_assert_size!(Local<'_>, 64);
+ static_assert_size!(Param<'_>, 32);
+ static_assert_size!(Pat<'_>, 88);
+ static_assert_size!(PatKind<'_>, 64);
+ static_assert_size!(Path<'_>, 48);
+ static_assert_size!(PathSegment<'_>, 56);
+ static_assert_size!(QPath<'_>, 24);
+ static_assert_size!(Stmt<'_>, 32);
+ static_assert_size!(StmtKind<'_>, 16);
+ static_assert_size!(TraitItem<'_>, 96);
+ static_assert_size!(TraitItemKind<'_>, 56);
+ static_assert_size!(Ty<'_>, 72);
+ static_assert_size!(TyKind<'_>, 56);
}
}
impl HirId {
+ /// Signal local id which should never be used.
+ pub const INVALID: HirId = HirId { owner: CRATE_DEF_ID, local_id: ItemLocalId::INVALID };
+
#[inline]
pub fn expect_owner(self) -> LocalDefId {
assert_eq!(self.local_id.index(), 0);
segment: &'v PathSegment<'v>,
) {
visitor.visit_ident(segment.ident);
- walk_list!(visitor, visit_id, segment.hir_id);
+ visitor.visit_id(segment.hir_id);
if let Some(ref args) = segment.args {
visitor.visit_generic_args(path_span, args);
}
visitor.visit_expr(callee_expression);
walk_list!(visitor, visit_expr, arguments);
}
- ExprKind::MethodCall(ref segment, arguments, _) => {
+ ExprKind::MethodCall(ref segment, receiver, arguments, _) => {
visitor.visit_path_segment(expression.span, segment);
+ visitor.visit_expr(receiver);
walk_list!(visitor, visit_expr, arguments);
}
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1);
// language items relating to transmutability
- TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(6);
+ TransmuteOpts, sym::transmute_opts, transmute_opts, Target::Struct, GenericRequirement::Exact(0);
+ TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(3);
Add(Op), sym::add, add_trait, Target::Trait, GenericRequirement::Exact(1);
Sub(Op), sym::sub, sub_trait, Target::Trait, GenericRequirement::Exact(1);
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
Oom, sym::oom, oom, Target::Fn, GenericRequirement::None;
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
- ConstEvalSelect, sym::const_eval_select, const_eval_select, Target::Fn, GenericRequirement::Exact(4);
- ConstConstEvalSelect, sym::const_eval_select_ct,const_eval_select_ct, Target::Fn, GenericRequirement::Exact(4);
Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1);
self.print_call_post(args)
}
- fn print_expr_method_call(&mut self, segment: &hir::PathSegment<'_>, args: &[hir::Expr<'_>]) {
- let base_args = &args[1..];
- self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX);
+ fn print_expr_method_call(
+ &mut self,
+ segment: &hir::PathSegment<'_>,
+ receiver: &hir::Expr<'_>,
+ args: &[hir::Expr<'_>],
+ ) {
+ let base_args = args;
+ self.print_expr_maybe_paren(&receiver, parser::PREC_POSTFIX);
self.word(".");
self.print_ident(segment.ident);
let generic_args = segment.args();
if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
- self.print_generic_args(generic_args, segment.infer_args, true);
+ self.print_generic_args(generic_args, true);
}
self.print_call_post(base_args)
hir::ExprKind::Call(func, args) => {
self.print_expr_call(func, args);
}
- hir::ExprKind::MethodCall(segment, args, _) => {
- self.print_expr_method_call(segment, args);
+ hir::ExprKind::MethodCall(segment, receiver, args, _) => {
+ self.print_expr_method_call(segment, receiver, args);
}
hir::ExprKind::Binary(op, lhs, rhs) => {
self.print_expr_binary(op, lhs, rhs);
}
if segment.ident.name != kw::PathRoot {
self.print_ident(segment.ident);
- self.print_generic_args(segment.args(), segment.infer_args, colons_before_params);
+ self.print_generic_args(segment.args(), colons_before_params);
}
}
}
pub fn print_path_segment(&mut self, segment: &hir::PathSegment<'_>) {
if segment.ident.name != kw::PathRoot {
self.print_ident(segment.ident);
- self.print_generic_args(segment.args(), segment.infer_args, false);
+ self.print_generic_args(segment.args(), false);
}
}
}
if segment.ident.name != kw::PathRoot {
self.print_ident(segment.ident);
- self.print_generic_args(
- segment.args(),
- segment.infer_args,
- colons_before_params,
- );
+ self.print_generic_args(segment.args(), colons_before_params);
}
}
self.word("::");
let item_segment = path.segments.last().unwrap();
self.print_ident(item_segment.ident);
- self.print_generic_args(
- item_segment.args(),
- item_segment.infer_args,
- colons_before_params,
- )
+ self.print_generic_args(item_segment.args(), colons_before_params)
}
hir::QPath::TypeRelative(qself, item_segment) => {
// If we've got a compound-qualified-path, let's push an additional pair of angle
self.word("::");
self.print_ident(item_segment.ident);
- self.print_generic_args(
- item_segment.args(),
- item_segment.infer_args,
- colons_before_params,
- )
+ self.print_generic_args(item_segment.args(), colons_before_params)
}
hir::QPath::LangItem(lang_item, span, _) => {
self.word("#[lang = \"");
fn print_generic_args(
&mut self,
generic_args: &hir::GenericArgs<'_>,
- infer_args: bool,
colons_before_params: bool,
) {
if generic_args.parenthesized {
);
}
- // FIXME(eddyb): this would leak into error messages (e.g.,
- // "non-exhaustive patterns: `Some::<..>(_)` not covered").
- if infer_args && false {
- start_or_comma(self);
- self.word("..");
- }
-
for binding in generic_args.bindings {
start_or_comma(self);
self.print_type_binding(binding);
pub fn print_type_binding(&mut self, binding: &hir::TypeBinding<'_>) {
self.print_ident(binding.ident);
- self.print_generic_args(binding.gen_args, false, false);
+ self.print_generic_args(binding.gen_args, false);
self.space();
match binding.kind {
hir::TypeBindingKind::Equality { ref term } => {
contains_exterior_struct_lit(x)
}
- hir::ExprKind::MethodCall(.., exprs, _) => {
+ hir::ExprKind::MethodCall(_, receiver, ..) => {
// `X { y: 1 }.bar(...)`
- contains_exterior_struct_lit(&exprs[0])
+ contains_exterior_struct_lit(receiver)
}
_ => false,
}
}
}
- hir::ExprKind::MethodCall(segment, _, _) => {
+ hir::ExprKind::MethodCall(segment, ..) => {
if let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) {
let generics = tcx.generics_of(def_id);
let insertable: Option<_> = try {
None?
}
let substs = self.node_substs_opt(expr.hir_id)?;
- let span = tcx.hir().span(segment.hir_id?);
+ let span = tcx.hir().span(segment.hir_id);
let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
InsertableGenericArgs {
insert_span,
path.segments
.iter()
.filter_map(move |segment| {
- let res = segment.res?;
+ let res = segment.res;
let generics_def_id = tcx.res_generics_def_id(res)?;
let generics = tcx.generics_of(generics_def_id);
if generics.has_impl_trait() {
return None;
}
- let span = tcx.hir().span(segment.hir_id?);
+ let span = tcx.hir().span(segment.hir_id);
let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
Some(InsertableGenericArgs {
insert_span,
if !segment.infer_args || generics.has_impl_trait() {
None?;
}
- let span = tcx.hir().span(segment.hir_id?);
+ let span = tcx.hir().span(segment.hir_id);
let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
InsertableGenericArgs { insert_span, substs, generics_def_id: def_id, def_id }
};
let generic_args = &generics.own_substs_no_defaults(tcx, substs)
[generics.own_counts().lifetimes..];
let span = match expr.kind {
- ExprKind::MethodCall(path, _, _) => path.ident.span,
+ ExprKind::MethodCall(path, ..) => path.ident.span,
_ => expr.span,
};
})
.any(|generics| generics.has_impl_trait())
};
- if let ExprKind::MethodCall(path, args, span) = expr.kind
+ if let ExprKind::MethodCall(path, receiver, args, span) = expr.kind
&& let Some(substs) = self.node_substs_opt(expr.hir_id)
&& substs.iter().any(|arg| self.generic_arg_contains_target(arg))
&& let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
&& !has_impl_trait(def_id)
{
let successor =
- args.get(1).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
+ args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
let substs = self.infcx.resolve_vars_if_possible(substs);
self.update_infer_source(InferSource {
span: path.ident.span,
kind: InferSourceKind::FullyQualifiedMethodCall {
- receiver: args.first().unwrap(),
+ receiver,
successor,
substs,
def_id,
}
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
[segment]
- if segment
- .res
- .map(|res| {
- matches!(
- res,
- Res::SelfTy { trait_: _, alias_to: _ }
- | Res::Def(hir::def::DefKind::TyParam, _)
- )
- })
- .unwrap_or(false) =>
+ if matches!(
+ segment.res,
+ Res::SelfTy { trait_: _, alias_to: _ }
+ | Res::Def(hir::def::DefKind::TyParam, _)
+ ) =>
{
self.types.push(path.span);
}
}
if sess.opts.unstable_opts.hir_stats {
- hir_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS");
+ hir_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1");
}
Ok(krate)
}
if sess.opts.unstable_opts.hir_stats {
- hir_stats::print_ast_stats(&krate, "POST EXPANSION AST STATS");
+ hir_stats::print_ast_stats(&krate, "POST EXPANSION AST STATS", "ast-stats-2");
}
resolver.resolve_crate(&krate);
}
// We only care about method call expressions.
- if let hir::ExprKind::MethodCall(call, args, _) = &expr.kind {
+ if let hir::ExprKind::MethodCall(call, receiver_arg, ..) = &expr.kind {
if call.ident.name != sym::into_iter {
return;
}
};
// As this is a method call expression, we have at least one argument.
- let receiver_arg = &args[0];
let receiver_ty = cx.typeck_results().expr_ty(receiver_arg);
let adjustments = cx.typeck_results().expr_adjustments(receiver_arg);
_ => {}
}
}
- } else if let hir::ExprKind::MethodCall(_, ref args, _) = expr.kind {
+ } else if let hir::ExprKind::MethodCall(_, receiver, ..) = expr.kind {
// Find problematic calls to `MaybeUninit::assume_init`.
let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
if cx.tcx.is_diagnostic_item(sym::assume_init, def_id) {
// This is a call to *some* method named `assume_init`.
// See if the `self` parameter is one of the dangerous constructors.
- if let hir::ExprKind::Call(ref path_expr, _) = args[0].kind {
+ if let hir::ExprKind::Call(ref path_expr, _) = receiver.kind {
if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
match cx.tcx.get_diagnostic_name(def_id) {
}
}
}
+
+pub use rustc_session::lint::builtin::UNEXPECTED_CFGS;
+
+declare_lint_pass!(UnexpectedCfgs => [UNEXPECTED_CFGS]);
+
+impl EarlyLintPass for UnexpectedCfgs {
+ fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
+ let cfg = &cx.sess().parse_sess.config;
+ let check_cfg = &cx.sess().parse_sess.check_config;
+ for &(name, value) in cfg {
+ if let Some(names_valid) = &check_cfg.names_valid {
+ if !names_valid.contains(&name) {
+ cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| {
+ diag.build(fluent::lint::builtin_unexpected_cli_config_name)
+ .help(fluent::lint::help)
+ .set_arg("name", name)
+ .emit();
+ });
+ }
+ }
+ if let Some(value) = value {
+ if let Some(values) = &check_cfg.values_valid.get(&name) {
+ if !values.contains(&value) {
+ cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| {
+ diag.build(fluent::lint::builtin_unexpected_cli_config_value)
+ .help(fluent::lint::help)
+ .set_arg("name", name)
+ .set_arg("value", value)
+ .emit();
+ });
+ }
+ }
+ }
+ }
+ }
+}
if let Some(positional_arg_to_replace) = position_sp_to_replace {
let name = if is_formatting_arg { named_arg_name + "$" } else { named_arg_name };
let span_to_replace = if let Ok(positional_arg_content) =
- self.sess().source_map().span_to_snippet(positional_arg_to_replace) && positional_arg_content.starts_with(":") {
+ self.sess().source_map().span_to_snippet(positional_arg_to_replace) && positional_arg_content.starts_with(':') {
positional_arg_to_replace.shrink_to_lo()
} else {
positional_arg_to_replace
expr: &Expr<'_>,
) -> Option<(Span, DefId, ty::subst::SubstsRef<'tcx>)> {
match expr.kind {
- ExprKind::MethodCall(segment, _, _)
+ ExprKind::MethodCall(segment, ..)
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) =>
{
Some((segment.ident.span, def_id, cx.typeck_results().node_substs(expr.hir_id)))
_: rustc_hir::HirId,
) {
if let Some(segment) = path.segments.iter().nth_back(1)
- && let Some(res) = &segment.res
- && lint_ty_kind_usage(cx, res)
+ && lint_ty_kind_usage(cx, &segment.res)
{
let span = path.span.with_hi(
segment.args.map_or(segment.ident.span, |a| a.span_ext).hi()
IncompleteFeatures: IncompleteFeatures,
RedundantSemicolons: RedundantSemicolons,
UnusedDocComment: UnusedDocComment,
+ UnexpectedCfgs: UnexpectedCfgs,
]
);
};
fn first_method_call<'tcx>(
expr: &'tcx Expr<'tcx>,
-) -> Option<(&'tcx PathSegment<'tcx>, &'tcx [Expr<'tcx>])> {
- if let ExprKind::MethodCall(path, args, _) = &expr.kind {
- if args.iter().any(|e| e.span.from_expansion()) { None } else { Some((path, *args)) }
+) -> Option<(&'tcx PathSegment<'tcx>, &'tcx Expr<'tcx>)> {
+ if let ExprKind::MethodCall(path, receiver, args, ..) = &expr.kind {
+ if args.iter().any(|e| e.span.from_expansion()) || receiver.span.from_expansion() {
+ None
+ } else {
+ Some((path, *receiver))
+ }
} else {
None
}
}
match first_method_call(expr) {
- Some((path, args)) if path.ident.name == sym::as_ptr => {
- let unwrap_arg = &args[0];
+ Some((path, unwrap_arg)) if path.ident.name == sym::as_ptr => {
let as_ptr_span = path.ident.span;
match first_method_call(unwrap_arg) {
- Some((path, args))
+ Some((path, receiver))
if path.ident.name == sym::unwrap || path.ident.name == sym::expect =>
{
- let source_arg = &args[0];
- lint_cstring_as_ptr(cx, as_ptr_span, source_arg, unwrap_arg);
+ lint_cstring_as_ptr(cx, as_ptr_span, receiver, unwrap_arg);
}
_ => return,
}
impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
// We only care about method calls.
- let ExprKind::MethodCall(call, elements, _) = &expr.kind else {
+ let ExprKind::MethodCall(call, receiver, ..) = &expr.kind else {
return
};
// We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow`
) {
return;
}
- let receiver = &elements[0];
let receiver_ty = cx.typeck_results().expr_ty(receiver);
let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
if receiver_ty != expr_ty {
sym::AtomicI64,
sym::AtomicI128,
];
- if let ExprKind::MethodCall(ref method_path, args, _) = &expr.kind
+ if let ExprKind::MethodCall(ref method_path, _, args, _) = &expr.kind
&& recognized_names.contains(&method_path.ident.name)
&& let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
&& let Some(impl_did) = cx.tcx.impl_of_method(m_def_id)
fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) {
if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store])
&& let Some((ordering_arg, invalid_ordering)) = match method {
- sym::load => Some((&args[1], sym::Release)),
- sym::store => Some((&args[2], sym::Acquire)),
+ sym::load => Some((&args[0], sym::Release)),
+ sym::store => Some((&args[1], sym::Acquire)),
_ => None,
}
&& let Some(ordering) = Self::match_ordering(cx, ordering_arg)
else {return };
let fail_order_arg = match method {
- sym::fetch_update => &args[2],
- sym::compare_exchange | sym::compare_exchange_weak => &args[4],
+ sym::fetch_update => &args[1],
+ sym::compare_exchange | sym::compare_exchange_weak => &args[3],
_ => return,
};
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
DUPLICATE_MACRO_ATTRIBUTES,
SUSPICIOUS_AUTO_TRAIT_IMPLS,
- UNEXPECTED_CFGS,
DEPRECATED_WHERE_CLAUSE_LOCATION,
TEST_UNSTABLE_LINT,
FFI_UNWIND_CALLS,
///
/// ### Example of drop reorder
///
- /// ```rust,compile_fail
+ /// ```rust,edition2018,compile_fail
/// #![deny(rust_2021_incompatible_closure_captures)]
/// # #![allow(unused)]
///
///
/// ### Example of auto-trait
///
- /// ```rust,compile_fail
+ /// ```rust,edition2018,compile_fail
/// #![deny(rust_2021_incompatible_closure_captures)]
/// use std::thread;
///
//! Validates all used crates and extern libraries and loads their metadata
+use crate::errors::{
+ ConflictingGlobalAlloc, CrateNotPanicRuntime, GlobalAllocRequired, NoMultipleGlobalAlloc,
+ NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore,
+};
use crate::locator::{CrateError, CrateLocator, CratePaths};
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
// Sanity check the loaded crate to ensure it is indeed a panic runtime
// and the panic strategy is indeed what we thought it was.
if !data.is_panic_runtime() {
- self.sess.err(&format!("the crate `{}` is not a panic runtime", name));
+ self.sess.emit_err(CrateNotPanicRuntime { crate_name: name });
}
if data.required_panic_strategy() != Some(desired_strategy) {
- self.sess.err(&format!(
- "the crate `{}` does not have the panic \
- strategy `{}`",
- name,
- desired_strategy.desc()
- ));
+ self.sess.emit_err(NoPanicStrategy { crate_name: name, strategy: desired_strategy });
}
self.cstore.injected_panic_runtime = Some(cnum);
let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime);
if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
- self.sess.err(
- "`profiler_builtins` crate (required by compiler options) \
- is not compatible with crate attribute `#![no_core]`",
- );
+ self.sess.emit_err(ProfilerBuiltinsNeedsCore);
}
let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
// Sanity check the loaded crate to ensure it is indeed a profiler runtime
if !data.is_profiler_runtime() {
- self.sess.err(&format!("the crate `{}` is not a profiler runtime", name));
+ self.sess.emit_err(NotProfilerRuntime { crate_name: name });
}
}
fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) {
[span1, span2, ..] => {
- self.sess
- .struct_span_err(*span2, "cannot define multiple global allocators")
- .span_label(*span2, "cannot define a new global allocator")
- .span_label(*span1, "previous global allocator defined here")
- .emit();
+ self.sess.emit_err(NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
true
}
spans => !spans.is_empty(),
if data.has_global_allocator() {
match global_allocator {
Some(other_crate) => {
- self.sess.err(&format!(
- "the `#[global_allocator]` in {} conflicts with global allocator in: {}",
- other_crate,
- data.name()
- ));
+ self.sess.emit_err(ConflictingGlobalAlloc {
+ crate_name: data.name(),
+ other_crate_name: other_crate,
+ });
}
None => global_allocator = Some(data.name()),
}
if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator)
&& !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator())
{
- self.sess.err(
- "no global memory allocator found but one is required; link to std or add \
- `#[global_allocator]` to a static item that implements the GlobalAlloc trait",
- );
+ self.sess.emit_err(GlobalAllocRequired);
}
self.cstore.allocator_kind = Some(AllocatorKind::Default);
}
for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) {
let data = self.cstore.get_crate_data(dep);
if needs_dep(&data) {
- self.sess.err(&format!(
- "the crate `{}` cannot depend \
- on a crate that needs {}, but \
- it depends on `{}`",
- self.cstore.get_crate_data(krate).name(),
- what,
- data.name()
- ));
+ self.sess.emit_err(NoTransitiveNeedsDep {
+ crate_name: self.cstore.get_crate_data(krate).name(),
+ needs_crate_name: what,
+ deps_crate_name: data.name(),
+ });
}
}
//! than finding a number of solutions (there are normally quite a few).
use crate::creader::CStore;
+use crate::errors::{
+ BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired,
+ RequiredPanicStrategy, RlibRequired, TwoPanicRuntimes,
+};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::CrateNum;
if src.rlib.is_some() {
continue;
}
- sess.err(&format!(
- "crate `{}` required to be available in rlib format, \
- but was not found in this form",
- tcx.crate_name(cnum)
- ));
+ sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
}
return Vec::new();
}
Linkage::Static => "rlib",
_ => "dylib",
};
- sess.err(&format!(
- "crate `{}` required to be available in {} format, \
- but was not found in this form",
- tcx.crate_name(cnum),
- kind
- ));
+ sess.emit_err(LibRequired { crate_name: tcx.crate_name(cnum), kind: kind });
}
}
}
// This error is probably a little obscure, but I imagine that it
// can be refined over time.
if link2 != link || link == RequireStatic {
- tcx.sess
- .struct_err(&format!(
- "cannot satisfy dependencies so `{}` only \
- shows up once",
- tcx.crate_name(cnum)
- ))
- .help(
- "having upstream crates all available in one format \
- will likely make this go away",
- )
- .emit();
+ tcx.sess.emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum) });
}
}
None => {
if let Some((prev, _)) = panic_runtime {
let prev_name = tcx.crate_name(prev);
let cur_name = tcx.crate_name(cnum);
- sess.err(&format!(
- "cannot link together two \
- panic runtimes: {} and {}",
- prev_name, cur_name
- ));
+ sess.emit_err(TwoPanicRuntimes { prev_name, cur_name });
}
panic_runtime = Some((
cnum,
// First up, validate that our selected panic runtime is indeed exactly
// our same strategy.
if found_strategy != desired_strategy {
- sess.err(&format!(
- "the linked panic runtime `{}` is \
- not compiled with this crate's \
- panic strategy `{}`",
- tcx.crate_name(runtime_cnum),
- desired_strategy.desc()
- ));
+ sess.emit_err(BadPanicStrategy {
+ runtime: tcx.crate_name(runtime_cnum),
+ strategy: desired_strategy,
+ });
}
// Next up, verify that all other crates are compatible with this panic
}
if let Some(found_strategy) = tcx.required_panic_strategy(cnum) && desired_strategy != found_strategy {
- sess.err(&format!(
- "the crate `{}` requires \
- panic strategy `{}` which is \
- incompatible with this crate's \
- strategy of `{}`",
- tcx.crate_name(cnum),
- found_strategy.desc(),
- desired_strategy.desc()
- ));
+ sess.emit_err(RequiredPanicStrategy {
+ crate_name: tcx.crate_name(cnum),
+ found_strategy,
+ desired_strategy});
}
let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy {
- sess.err(&format!(
- "the crate `{}` is compiled with the \
- panic-in-drop strategy `{}` which is \
- incompatible with this crate's \
- strategy of `{}`",
- tcx.crate_name(cnum),
- found_drop_strategy.desc(),
- tcx.sess.opts.unstable_opts.panic_in_drop.desc()
- ));
+ sess.emit_err(IncompatiblePanicInDropStrategy {
+ crate_name: tcx.crate_name(cnum),
+ found_strategy: found_drop_strategy,
+ desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
+ });
}
}
}
--- /dev/null
+use std::{
+ io::Error,
+ path::{Path, PathBuf},
+};
+
+use rustc_errors::{error_code, ErrorGuaranteed};
+use rustc_macros::SessionDiagnostic;
+use rustc_session::{config, SessionDiagnostic};
+use rustc_span::{sym, Span, Symbol};
+use rustc_target::spec::{PanicStrategy, TargetTriple};
+
+use crate::locator::CrateFlavor;
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::rlib_required)]
+pub struct RlibRequired {
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::lib_required)]
+pub struct LibRequired<'a> {
+ pub crate_name: Symbol,
+ pub kind: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::crate_dep_multiple)]
+#[help]
+pub struct CrateDepMultiple {
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::two_panic_runtimes)]
+pub struct TwoPanicRuntimes {
+ pub prev_name: Symbol,
+ pub cur_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::bad_panic_strategy)]
+pub struct BadPanicStrategy {
+ pub runtime: Symbol,
+ pub strategy: PanicStrategy,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::required_panic_strategy)]
+pub struct RequiredPanicStrategy {
+ pub crate_name: Symbol,
+ pub found_strategy: PanicStrategy,
+ pub desired_strategy: PanicStrategy,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::incompatible_panic_in_drop_strategy)]
+pub struct IncompatiblePanicInDropStrategy {
+ pub crate_name: Symbol,
+ pub found_strategy: PanicStrategy,
+ pub desired_strategy: PanicStrategy,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_names_in_link)]
+pub struct MultipleNamesInLink {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_kinds_in_link)]
+pub struct MultipleKindsInLink {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_name_form)]
+pub struct LinkNameForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_kind_form)]
+pub struct LinkKindForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_modifiers_form)]
+pub struct LinkModifiersForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_cfg_form)]
+pub struct LinkCfgForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::wasm_import_form)]
+pub struct WasmImportForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::empty_link_name, code = "E0454")]
+pub struct EmptyLinkName {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_framework_apple, code = "E0455")]
+pub struct LinkFrameworkApple {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::framework_only_windows, code = "E0455")]
+pub struct FrameworkOnlyWindows {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unknown_link_kind, code = "E0458")]
+pub struct UnknownLinkKind<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub kind: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_link_modifiers)]
+pub struct MultipleLinkModifiers {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_cfgs)]
+pub struct MultipleCfgs {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_cfg_single_predicate)]
+pub struct LinkCfgSinglePredicate {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_wasm_import)]
+pub struct MultipleWasmImport {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unexpected_link_arg)]
+pub struct UnexpectedLinkArg {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::invalid_link_modifier)]
+pub struct InvalidLinkModifier {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_modifiers)]
+pub struct MultipleModifiers<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub modifier: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::bundle_needs_static)]
+pub struct BundleNeedsStatic {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::whole_archive_needs_static)]
+pub struct WholeArchiveNeedsStatic {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::as_needed_compatibility)]
+pub struct AsNeededCompatibility {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unknown_link_modifier)]
+pub struct UnknownLinkModifier<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub modifier: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::incompatible_wasm_link)]
+pub struct IncompatibleWasmLink {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_requires_name, code = "E0459")]
+pub struct LinkRequiresName {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::raw_dylib_no_nul)]
+pub struct RawDylibNoNul {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_ordinal_raw_dylib)]
+pub struct LinkOrdinalRawDylib {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::lib_framework_apple)]
+pub struct LibFrameworkApple;
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::empty_renaming_target)]
+pub struct EmptyRenamingTarget<'a> {
+ pub lib_name: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::renaming_no_link)]
+pub struct RenamingNoLink<'a> {
+ pub lib_name: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_renamings)]
+pub struct MultipleRenamings<'a> {
+ pub lib_name: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_link_mod_override)]
+pub struct NoLinkModOverride {
+ #[primary_span]
+ pub span: Option<Span>,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unsupported_abi_i686)]
+pub struct UnsupportedAbiI686 {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unsupported_abi)]
+pub struct UnsupportedAbi {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::fail_create_file_encoder)]
+pub struct FailCreateFileEncoder {
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::fail_seek_file)]
+pub struct FailSeekFile {
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::fail_write_file)]
+pub struct FailWriteFile {
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::crate_not_panic_runtime)]
+pub struct CrateNotPanicRuntime {
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_panic_strategy)]
+pub struct NoPanicStrategy {
+ pub crate_name: Symbol,
+ pub strategy: PanicStrategy,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::profiler_builtins_needs_core)]
+pub struct ProfilerBuiltinsNeedsCore;
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::not_profiler_runtime)]
+pub struct NotProfilerRuntime {
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_multiple_global_alloc)]
+pub struct NoMultipleGlobalAlloc {
+ #[primary_span]
+ #[label]
+ pub span2: Span,
+ #[label(metadata::prev_global_alloc)]
+ pub span1: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::conflicting_global_alloc)]
+pub struct ConflictingGlobalAlloc {
+ pub crate_name: Symbol,
+ pub other_crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::global_alloc_required)]
+pub struct GlobalAllocRequired;
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_transitive_needs_dep)]
+pub struct NoTransitiveNeedsDep<'a> {
+ pub crate_name: Symbol,
+ pub needs_crate_name: &'a str,
+ pub deps_crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::failed_write_error)]
+pub struct FailedWriteError {
+ pub filename: PathBuf,
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::failed_create_tempdir)]
+pub struct FailedCreateTempdir {
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::failed_create_file)]
+pub struct FailedCreateFile<'a> {
+ pub filename: &'a Path,
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::failed_create_encoded_metadata)]
+pub struct FailedCreateEncodedMetadata {
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::non_ascii_name)]
+pub struct NonAsciiName {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::extern_location_not_exist)]
+pub struct ExternLocationNotExist<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub location: &'a Path,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::extern_location_not_file)]
+pub struct ExternLocationNotFile<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub location: &'a Path,
+}
+
+pub(crate) struct MultipleCandidates {
+ pub span: Span,
+ pub flavor: CrateFlavor,
+ pub crate_name: Symbol,
+ pub candidates: Vec<PathBuf>,
+}
+
+impl SessionDiagnostic<'_> for MultipleCandidates {
+ fn into_diagnostic(
+ self,
+ sess: &'_ rustc_session::parse::ParseSess,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = sess.struct_err(rustc_errors::fluent::metadata::multiple_candidates);
+ diag.set_arg("crate_name", self.crate_name);
+ diag.set_arg("flavor", self.flavor);
+ diag.code(error_code!(E0465));
+ diag.set_span(self.span);
+ for (i, candidate) in self.candidates.iter().enumerate() {
+ diag.span_note(self.span, &format!("candidate #{}: {}", i + 1, candidate.display()));
+ }
+ diag
+ }
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_matching_crates, code = "E0464")]
+#[note]
+pub struct MultipleMatchingCrates {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub candidates: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::symbol_conflicts_current, code = "E0519")]
+pub struct SymbolConflictsCurrent {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::symbol_conflicts_others, code = "E0523")]
+pub struct SymbolConflictsOthers {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::stable_crate_id_collision)]
+pub struct StableCrateIdCollision {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name0: Symbol,
+ pub crate_name1: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::dl_error)]
+pub struct DlError {
+ #[primary_span]
+ pub span: Span,
+ pub err: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::newer_crate_version, code = "E0460")]
+#[note]
+#[note(metadata::found_crate_versions)]
+pub struct NewerCrateVersion {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub add_info: String,
+ pub found_crates: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_crate_with_triple, code = "E0461")]
+#[note(metadata::found_crate_versions)]
+pub struct NoCrateWithTriple<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub locator_triple: &'a str,
+ pub add_info: String,
+ pub found_crates: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::found_staticlib, code = "E0462")]
+#[note(metadata::found_crate_versions)]
+#[help]
+pub struct FoundStaticlib {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub add_info: String,
+ pub found_crates: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::incompatible_rustc, code = "E0514")]
+#[note(metadata::found_crate_versions)]
+#[help]
+pub struct IncompatibleRustc {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub add_info: String,
+ pub found_crates: String,
+ pub rustc_version: String,
+}
+
+pub struct InvalidMetadataFiles {
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub add_info: String,
+ pub crate_rejections: Vec<String>,
+}
+
+impl SessionDiagnostic<'_> for InvalidMetadataFiles {
+ fn into_diagnostic(
+ self,
+ sess: &'_ rustc_session::parse::ParseSess,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = sess.struct_err(rustc_errors::fluent::metadata::invalid_meta_files);
+ diag.set_arg("crate_name", self.crate_name);
+ diag.set_arg("add_info", self.add_info);
+ diag.code(error_code!(E0786));
+ diag.set_span(self.span);
+ for crate_rejection in self.crate_rejections {
+ diag.note(crate_rejection);
+ }
+ diag
+ }
+}
+
+pub struct CannotFindCrate {
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub add_info: String,
+ pub missing_core: bool,
+ pub current_crate: String,
+ pub is_nightly_build: bool,
+ pub profiler_runtime: Symbol,
+ pub locator_triple: TargetTriple,
+}
+
+impl SessionDiagnostic<'_> for CannotFindCrate {
+ fn into_diagnostic(
+ self,
+ sess: &'_ rustc_session::parse::ParseSess,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = sess.struct_err(rustc_errors::fluent::metadata::cannot_find_crate);
+ diag.set_arg("crate_name", self.crate_name);
+ diag.set_arg("add_info", self.add_info);
+ diag.set_arg("locator_triple", self.locator_triple.triple());
+ diag.code(error_code!(E0463));
+ diag.set_span(self.span);
+ if (self.crate_name == sym::std || self.crate_name == sym::core)
+ && self.locator_triple != TargetTriple::from_triple(config::host_triple())
+ {
+ if self.missing_core {
+ diag.note(rustc_errors::fluent::metadata::target_not_installed);
+ } else {
+ diag.note(rustc_errors::fluent::metadata::target_no_std_support);
+ }
+ // NOTE: this suggests using rustup, even though the user may not have it installed.
+ // That's because they could choose to install it; or this may give them a hint which
+ // target they need to install from their distro.
+ if self.missing_core {
+ diag.help(rustc_errors::fluent::metadata::consider_downloading_target);
+ }
+ // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway.
+ // NOTE: this is a dummy span if `extern crate std` was injected by the compiler.
+ // If it's not a dummy, that means someone added `extern crate std` explicitly and
+ // `#![no_std]` won't help.
+ if !self.missing_core && self.span.is_dummy() {
+ diag.note(rustc_errors::fluent::metadata::std_required);
+ }
+ if self.is_nightly_build {
+ diag.help(rustc_errors::fluent::metadata::consider_building_std);
+ }
+ } else if self.crate_name == self.profiler_runtime {
+ diag.note(rustc_errors::fluent::metadata::compiler_missing_profiler);
+ } else if self.crate_name.as_str().starts_with("rustc_") {
+ diag.help(rustc_errors::fluent::metadata::install_missing_components);
+ }
+ diag.span_label(self.span, rustc_errors::fluent::metadata::cant_find_crate);
+ diag
+ }
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_dylib_plugin, code = "E0457")]
+pub struct NoDylibPlugin {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::crate_location_unknown_type)]
+pub struct CrateLocationUnknownType<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub path: &'a Path,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::lib_filename_form)]
+pub struct LibFilenameForm<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub dll_prefix: &'a str,
+ pub dll_suffix: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_import_name_type)]
+pub struct MultipleImportNameType {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::import_name_type_form)]
+pub struct ImportNameTypeForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::import_name_type_x86)]
+pub struct ImportNameTypeX86 {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unknown_import_name_type)]
+pub struct UnknownImportNameType<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub import_name_type: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::import_name_type_raw)]
+pub struct ImportNameTypeRaw {
+ #[primary_span]
+ pub span: Span,
+}
+use crate::errors::{
+ FailedCreateEncodedMetadata, FailedCreateFile, FailedCreateTempdir, FailedWriteError,
+};
use crate::{encode_metadata, EncodedMetadata};
use rustc_data_structures::temp_dir::MaybeTempDir;
let out_filename = tmpdir.as_ref().join(METADATA_FILENAME);
let result = fs::write(&out_filename, metadata);
- if let Err(e) = result {
- sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
+ if let Err(err) = result {
+ sess.emit_fatal(FailedWriteError { filename: out_filename, err });
}
out_filename
let metadata_tmpdir = TempFileBuilder::new()
.prefix("rmeta")
.tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new("")))
- .unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)));
+ .unwrap_or_else(|err| tcx.sess.emit_fatal(FailedCreateTempdir { err }));
let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME);
// This simplifies the creation of the output `out_filename` when requested.
match metadata_kind {
MetadataKind::None => {
- std::fs::File::create(&metadata_filename).unwrap_or_else(|e| {
- tcx.sess.fatal(&format!(
- "failed to create the file {}: {}",
- metadata_filename.display(),
- e
- ))
+ std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
+ tcx.sess.emit_fatal(FailedCreateFile { filename: &metadata_filename, err });
});
}
MetadataKind::Uncompressed | MetadataKind::Compressed => {
// this file always exists.
let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata);
let (metadata_filename, metadata_tmpdir) = if need_metadata_file {
- if let Err(e) = non_durable_rename(&metadata_filename, &out_filename) {
- tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
+ if let Err(err) = non_durable_rename(&metadata_filename, &out_filename) {
+ tcx.sess.emit_fatal(FailedWriteError { filename: out_filename, err });
}
if tcx.sess.opts.json_artifact_notifications {
tcx.sess
// Load metadata back to memory: codegen may need to include it in object files.
let metadata =
- EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|e| {
- tcx.sess.fatal(&format!("failed to create encoded metadata from file: {}", e))
+ EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| {
+ tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err });
});
let need_metadata_module = metadata_kind == MetadataKind::Compressed;
#![feature(never_type)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
extern crate proc_macro;
mod rmeta;
pub mod creader;
+pub mod errors;
pub mod fs;
pub mod locator;
//! metadata::locator or metadata::creader for all the juicy details!
use crate::creader::Library;
+use crate::errors::{
+ CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist,
+ ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles,
+ LibFilenameForm, MultipleCandidates, MultipleMatchingCrates, NewerCrateVersion,
+ NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent,
+ SymbolConflictsOthers,
+};
use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::owning_ref::OwningRef;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MetadataRef;
-use rustc_errors::{struct_span_err, FatalError};
+use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
use rustc_session::config::{self, CrateType};
use rustc_session::cstore::{CrateSource, MetadataLoader};
use rustc_session::filesearch::FileSearch;
use rustc_session::search_paths::PathKind;
use rustc_session::utils::CanonicalizedPath;
use rustc_session::Session;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::Symbol;
use rustc_span::Span;
use rustc_target::spec::{Target, TargetTriple};
use snap::read::FrameDecoder;
+use std::borrow::Cow;
use std::fmt::Write as _;
use std::io::{Read, Result as IoResult, Write};
use std::path::{Path, PathBuf};
}
}
+impl IntoDiagnosticArg for CrateFlavor {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ match self {
+ CrateFlavor::Rlib => DiagnosticArgValue::Str(Cow::Borrowed("rlib")),
+ CrateFlavor::Rmeta => DiagnosticArgValue::Str(Cow::Borrowed("rmeta")),
+ CrateFlavor::Dylib => DiagnosticArgValue::Str(Cow::Borrowed("dylib")),
+ }
+ }
+}
+
impl<'a> CrateLocator<'a> {
pub(crate) fn new(
sess: &'a Session,
impl CrateError {
pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) {
- let mut diag = match self {
- CrateError::NonAsciiName(crate_name) => sess.struct_span_err(
- span,
- &format!("cannot load a crate with a non-ascii name `{}`", crate_name),
- ),
- CrateError::ExternLocationNotExist(crate_name, loc) => sess.struct_span_err(
- span,
- &format!("extern location for {} does not exist: {}", crate_name, loc.display()),
- ),
- CrateError::ExternLocationNotFile(crate_name, loc) => sess.struct_span_err(
- span,
- &format!("extern location for {} is not a file: {}", crate_name, loc.display()),
- ),
+ match self {
+ CrateError::NonAsciiName(crate_name) => {
+ sess.emit_err(NonAsciiName { span, crate_name });
+ }
+ CrateError::ExternLocationNotExist(crate_name, loc) => {
+ sess.emit_err(ExternLocationNotExist { span, crate_name, location: &loc });
+ }
+ CrateError::ExternLocationNotFile(crate_name, loc) => {
+ sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc });
+ }
CrateError::MultipleCandidates(crate_name, flavor, candidates) => {
- let mut err = struct_span_err!(
- sess,
- span,
- E0465,
- "multiple {} candidates for `{}` found",
- flavor,
- crate_name,
- );
- for (i, candidate) in candidates.iter().enumerate() {
- err.span_note(span, &format!("candidate #{}: {}", i + 1, candidate.display()));
- }
- err
+ sess.emit_err(MultipleCandidates { span, flavor: flavor, crate_name, candidates });
}
CrateError::MultipleMatchingCrates(crate_name, libraries) => {
- let mut err = struct_span_err!(
- sess,
- span,
- E0464,
- "multiple matching crates for `{}`",
- crate_name
- );
let mut libraries: Vec<_> = libraries.into_values().collect();
// Make ordering of candidates deterministic.
// This has to `clone()` to work around lifetime restrictions with `sort_by_key()`.
s
})
.collect::<String>();
- err.note(&format!("candidates:{}", candidates));
- err
+ sess.emit_err(MultipleMatchingCrates { span, crate_name, candidates });
+ }
+ CrateError::SymbolConflictsCurrent(root_name) => {
+ sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name });
+ }
+ CrateError::SymbolConflictsOthers(root_name) => {
+ sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name });
}
- CrateError::SymbolConflictsCurrent(root_name) => struct_span_err!(
- sess,
- span,
- E0519,
- "the current crate is indistinguishable from one of its dependencies: it has the \
- same crate-name `{}` and was compiled with the same `-C metadata` arguments. \
- This will result in symbol conflicts between the two.",
- root_name,
- ),
- CrateError::SymbolConflictsOthers(root_name) => struct_span_err!(
- sess,
- span,
- E0523,
- "found two different crates with name `{}` that are not distinguished by differing \
- `-C metadata`. This will result in symbol conflicts between the two.",
- root_name,
- ),
CrateError::StableCrateIdCollision(crate_name0, crate_name1) => {
- let msg = format!(
- "found crates (`{}` and `{}`) with colliding StableCrateId values.",
- crate_name0, crate_name1
- );
- sess.struct_span_err(span, &msg)
+ sess.emit_err(StableCrateIdCollision {
+ span,
+ crate_name0: crate_name0,
+ crate_name1: crate_name1,
+ });
+ }
+ CrateError::DlOpen(s) | CrateError::DlSym(s) => {
+ sess.emit_err(DlError { span, err: s });
}
- CrateError::DlOpen(s) | CrateError::DlSym(s) => sess.struct_span_err(span, &s),
CrateError::LocatorCombined(locator) => {
let crate_name = locator.crate_name;
- let add = match &locator.root {
+ let add_info = match &locator.root {
None => String::new(),
Some(r) => format!(" which `{}` depends on", r.name),
};
- let mut msg = "the following crate versions were found:".to_string();
- let mut err = if !locator.crate_rejections.via_hash.is_empty() {
- let mut err = struct_span_err!(
- sess,
- span,
- E0460,
- "found possibly newer version of crate `{}`{}",
- crate_name,
- add,
- );
- err.note("perhaps that crate needs to be recompiled?");
+ // FIXME: There are no tests for CrateLocationUnknownType or LibFilenameForm
+ if !locator.crate_rejections.via_filename.is_empty() {
+ let mismatches = locator.crate_rejections.via_filename.iter();
+ for CrateMismatch { path, .. } in mismatches {
+ sess.emit_err(CrateLocationUnknownType { span, path: &path });
+ sess.emit_err(LibFilenameForm {
+ span,
+ dll_prefix: &locator.dll_prefix,
+ dll_suffix: &locator.dll_suffix,
+ });
+ }
+ }
+ let mut found_crates = String::new();
+ if !locator.crate_rejections.via_hash.is_empty() {
let mismatches = locator.crate_rejections.via_hash.iter();
for CrateMismatch { path, .. } in mismatches {
- msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display()));
+ found_crates.push_str(&format!(
+ "\ncrate `{}`: {}",
+ crate_name,
+ path.display()
+ ));
}
if let Some(r) = locator.root {
for path in r.source.paths() {
- msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display()));
+ found_crates.push_str(&format!(
+ "\ncrate `{}`: {}",
+ r.name,
+ path.display()
+ ));
}
}
- err.note(&msg);
- err
- } else if !locator.crate_rejections.via_triple.is_empty() {
- let mut err = struct_span_err!(
- sess,
+ sess.emit_err(NewerCrateVersion {
span,
- E0461,
- "couldn't find crate `{}` with expected target triple {}{}",
- crate_name,
- locator.triple,
- add,
- );
+ crate_name: crate_name,
+ add_info,
+ found_crates,
+ });
+ } else if !locator.crate_rejections.via_triple.is_empty() {
let mismatches = locator.crate_rejections.via_triple.iter();
for CrateMismatch { path, got } in mismatches {
- msg.push_str(&format!(
+ found_crates.push_str(&format!(
"\ncrate `{}`, target triple {}: {}",
crate_name,
got,
path.display(),
));
}
- err.note(&msg);
- err
- } else if !locator.crate_rejections.via_kind.is_empty() {
- let mut err = struct_span_err!(
- sess,
+ sess.emit_err(NoCrateWithTriple {
span,
- E0462,
- "found staticlib `{}` instead of rlib or dylib{}",
- crate_name,
- add,
- );
- err.help("please recompile that crate using --crate-type lib");
+ crate_name: crate_name,
+ locator_triple: locator.triple.triple(),
+ add_info,
+ found_crates,
+ });
+ } else if !locator.crate_rejections.via_kind.is_empty() {
let mismatches = locator.crate_rejections.via_kind.iter();
for CrateMismatch { path, .. } in mismatches {
- msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display()));
+ found_crates.push_str(&format!(
+ "\ncrate `{}`: {}",
+ crate_name,
+ path.display()
+ ));
}
- err.note(&msg);
- err
+ sess.emit_err(FoundStaticlib { span, crate_name, add_info, found_crates });
} else if !locator.crate_rejections.via_version.is_empty() {
- let mut err = struct_span_err!(
- sess,
- span,
- E0514,
- "found crate `{}` compiled by an incompatible version of rustc{}",
- crate_name,
- add,
- );
- err.help(&format!(
- "please recompile that crate using this compiler ({}) \
- (consider running `cargo clean` first)",
- rustc_version(),
- ));
let mismatches = locator.crate_rejections.via_version.iter();
for CrateMismatch { path, got } in mismatches {
- msg.push_str(&format!(
+ found_crates.push_str(&format!(
"\ncrate `{}` compiled by {}: {}",
crate_name,
got,
path.display(),
));
}
- err.note(&msg);
- err
- } else if !locator.crate_rejections.via_invalid.is_empty() {
- let mut err = struct_span_err!(
- sess,
+ sess.emit_err(IncompatibleRustc {
span,
- E0786,
- "found invalid metadata files for crate `{}`{}",
crate_name,
- add,
- );
+ add_info,
+ found_crates,
+ rustc_version: rustc_version(),
+ });
+ } else if !locator.crate_rejections.via_invalid.is_empty() {
+ let mut crate_rejections = Vec::new();
for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid {
- err.note(&got);
+ crate_rejections.push(got);
}
- err
+ sess.emit_err(InvalidMetadataFiles {
+ span,
+ crate_name,
+ add_info,
+ crate_rejections,
+ });
} else {
- let mut err = struct_span_err!(
- sess,
+ sess.emit_err(CannotFindCrate {
span,
- E0463,
- "can't find crate for `{}`{}",
crate_name,
- add,
- );
-
- if (crate_name == sym::std || crate_name == sym::core)
- && locator.triple != TargetTriple::from_triple(config::host_triple())
- {
- if missing_core {
- err.note(&format!(
- "the `{}` target may not be installed",
- locator.triple
- ));
- } else {
- err.note(&format!(
- "the `{}` target may not support the standard library",
- locator.triple
- ));
- }
- // NOTE: this suggests using rustup, even though the user may not have it installed.
- // That's because they could choose to install it; or this may give them a hint which
- // target they need to install from their distro.
- if missing_core {
- err.help(&format!(
- "consider downloading the target with `rustup target add {}`",
- locator.triple
- ));
- }
- // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway.
- // NOTE: this is a dummy span if `extern crate std` was injected by the compiler.
- // If it's not a dummy, that means someone added `extern crate std` explicitly and `#![no_std]` won't help.
- if !missing_core && span.is_dummy() {
- let current_crate =
- sess.opts.crate_name.as_deref().unwrap_or("<unknown>");
- err.note(&format!(
- "`std` is required by `{}` because it does not declare `#![no_std]`",
- current_crate
- ));
- }
- if sess.is_nightly_build() {
- err.help("consider building the standard library from source with `cargo build -Zbuild-std`");
- }
- } else if crate_name
- == Symbol::intern(&sess.opts.unstable_opts.profiler_runtime)
- {
- err.note("the compiler may have been built without the profiler runtime");
- } else if crate_name.as_str().starts_with("rustc_") {
- err.help(
- "maybe you need to install the missing components with: \
- `rustup component add rust-src rustc-dev llvm-tools-preview`",
- );
- }
- err.span_label(span, "can't find crate");
- err
- };
-
- if !locator.crate_rejections.via_filename.is_empty() {
- let mismatches = locator.crate_rejections.via_filename.iter();
- for CrateMismatch { path, .. } in mismatches {
- err.note(&format!(
- "extern location for {} is of an unknown type: {}",
- crate_name,
- path.display(),
- ))
- .help(&format!(
- "file name should be lib*.rlib or {}*.{}",
- locator.dll_prefix, locator.dll_suffix
- ));
- }
+ add_info,
+ missing_core,
+ current_crate: sess
+ .opts
+ .crate_name
+ .clone()
+ .unwrap_or("<unknown>".to_string()),
+ is_nightly_build: sess.is_nightly_build(),
+ profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime),
+ locator_triple: locator.triple,
+ });
}
- err
}
- CrateError::NonDylibPlugin(crate_name) => struct_span_err!(
- sess,
- span,
- E0457,
- "plugin `{}` only found in rlib format, but must be available in dylib format",
- crate_name,
- ),
- };
-
- diag.emit();
+ CrateError::NonDylibPlugin(crate_name) => {
+ sess.emit_err(NoDylibPlugin { span, crate_name });
+ }
+ }
}
}
use rustc_ast::{NestedMetaItem, CRATE_NODE_ID};
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
use rustc_target::spec::abi::Abi;
+use crate::errors::{
+ AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget,
+ FrameworkOnlyWindows, ImportNameTypeForm, ImportNameTypeRaw, ImportNameTypeX86,
+ IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, LinkCfgForm,
+ LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, LinkNameForm,
+ LinkOrdinalRawDylib, LinkRequiresName, MultipleCfgs, MultipleImportNameType,
+ MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers, MultipleNamesInLink,
+ MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, RenamingNoLink,
+ UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier, UnsupportedAbi,
+ UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic,
+};
+
pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
let mut collector = Collector { tcx, libs: Vec::new() };
for id in tcx.hir().items() {
match item.name_or_empty() {
sym::name => {
if name.is_some() {
- let msg = "multiple `name` arguments in a single `#[link]` attribute";
- sess.span_err(item.span(), msg);
+ sess.emit_err(MultipleNamesInLink { span: item.span() });
continue;
}
let Some(link_name) = item.value_str() else {
- let msg = "link name must be of the form `name = \"string\"`";
- sess.span_err(item.span(), msg);
+ sess.emit_err(LinkNameForm { span: item.span() });
continue;
};
let span = item.name_value_literal_span().unwrap();
if link_name.is_empty() {
- struct_span_err!(sess, span, E0454, "link name must not be empty")
- .span_label(span, "empty link name")
- .emit();
+ sess.emit_err(EmptyLinkName { span });
}
name = Some((link_name, span));
}
sym::kind => {
if kind.is_some() {
- let msg = "multiple `kind` arguments in a single `#[link]` attribute";
- sess.span_err(item.span(), msg);
+ sess.emit_err(MultipleKindsInLink { span: item.span() });
continue;
}
let Some(link_kind) = item.value_str() else {
- let msg = "link kind must be of the form `kind = \"string\"`";
- sess.span_err(item.span(), msg);
+ sess.emit_err(LinkKindForm { span: item.span() });
continue;
};
"dylib" => NativeLibKind::Dylib { as_needed: None },
"framework" => {
if !sess.target.is_like_osx {
- struct_span_err!(
- sess,
- span,
- E0455,
- "link kind `framework` is only supported on Apple targets"
- )
- .emit();
+ sess.emit_err(LinkFrameworkApple { span });
}
NativeLibKind::Framework { as_needed: None }
}
"raw-dylib" => {
if !sess.target.is_like_windows {
- struct_span_err!(
- sess,
- span,
- E0455,
- "link kind `raw-dylib` is only supported on Windows targets"
- )
- .emit();
+ sess.emit_err(FrameworkOnlyWindows { span });
} else if !features.raw_dylib {
feature_err(
&sess.parse_sess,
NativeLibKind::RawDylib
}
kind => {
- let msg = format!(
- "unknown link kind `{kind}`, expected one of: \
- static, dylib, framework, raw-dylib"
- );
- struct_span_err!(sess, span, E0458, "{}", msg)
- .span_label(span, "unknown link kind")
- .emit();
+ sess.emit_err(UnknownLinkKind { span, kind });
continue;
}
};
}
sym::modifiers => {
if modifiers.is_some() {
- let msg =
- "multiple `modifiers` arguments in a single `#[link]` attribute";
- sess.span_err(item.span(), msg);
+ sess.emit_err(MultipleLinkModifiers { span: item.span() });
continue;
}
let Some(link_modifiers) = item.value_str() else {
- let msg = "link modifiers must be of the form `modifiers = \"string\"`";
- sess.span_err(item.span(), msg);
+ sess.emit_err(LinkModifiersForm { span: item.span() });
continue;
};
modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
}
sym::cfg => {
if cfg.is_some() {
- let msg = "multiple `cfg` arguments in a single `#[link]` attribute";
- sess.span_err(item.span(), msg);
+ sess.emit_err(MultipleCfgs { span: item.span() });
continue;
}
let Some(link_cfg) = item.meta_item_list() else {
- let msg = "link cfg must be of the form `cfg(/* predicate */)`";
- sess.span_err(item.span(), msg);
+ sess.emit_err(LinkCfgForm { span: item.span() });
continue;
};
let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else {
- let msg = "link cfg must have a single predicate argument";
- sess.span_err(item.span(), msg);
+ sess.emit_err(LinkCfgSinglePredicate { span: item.span() });
continue;
};
if !features.link_cfg {
}
sym::wasm_import_module => {
if wasm_import_module.is_some() {
- let msg = "multiple `wasm_import_module` arguments \
- in a single `#[link]` attribute";
- sess.span_err(item.span(), msg);
+ sess.emit_err(MultipleWasmImport { span: item.span() });
continue;
}
let Some(link_wasm_import_module) = item.value_str() else {
- let msg = "wasm import module must be of the form \
- `wasm_import_module = \"string\"`";
- sess.span_err(item.span(), msg);
+ sess.emit_err(WasmImportForm { span: item.span() });
continue;
};
wasm_import_module = Some((link_wasm_import_module, item.span()));
}
sym::import_name_type => {
if import_name_type.is_some() {
- let msg = "multiple `import_name_type` arguments in a single `#[link]` attribute";
- sess.span_err(item.span(), msg);
+ sess.emit_err(MultipleImportNameType { span: item.span() });
continue;
}
let Some(link_import_name_type) = item.value_str() else {
- let msg = "import name type must be of the form `import_name_type = \"string\"`";
- sess.span_err(item.span(), msg);
+ sess.emit_err(ImportNameTypeForm { span: item.span() });
continue;
};
if self.tcx.sess.target.arch != "x86" {
- let msg = "import name type is only supported on x86";
- sess.span_err(item.span(), msg);
+ sess.emit_err(ImportNameTypeX86 { span: item.span() });
continue;
}
"noprefix" => PeImportNameType::NoPrefix,
"undecorated" => PeImportNameType::Undecorated,
import_name_type => {
- let msg = format!(
- "unknown import name type `{import_name_type}`, expected one of: \
- decorated, noprefix, undecorated"
- );
- sess.span_err(item.span(), msg);
+ sess.emit_err(UnknownImportNameType {
+ span: item.span(),
+ import_name_type,
+ });
continue;
}
};
import_name_type = Some((link_import_name_type, item.span()));
}
_ => {
- let msg = "unexpected `#[link]` argument, expected one of: \
- name, kind, modifiers, cfg, wasm_import_module, import_name_type";
- sess.span_err(item.span(), msg);
+ sess.emit_err(UnexpectedLinkArg { span: item.span() });
}
}
}
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
Some(m) => (m, modifier.starts_with('+')),
None => {
- sess.span_err(
- span,
- "invalid linking modifier syntax, expected '+' or '-' prefix \
- before one of: bundle, verbatim, whole-archive, as-needed",
- );
+ sess.emit_err(InvalidLinkModifier { span });
continue;
}
};
}
let assign_modifier = |dst: &mut Option<bool>| {
if dst.is_some() {
- let msg = format!(
- "multiple `{modifier}` modifiers in a single `modifiers` argument"
- );
- sess.span_err(span, &msg);
+ sess.emit_err(MultipleModifiers { span, modifier });
} else {
*dst = Some(value);
}
assign_modifier(bundle)
}
("bundle", _) => {
- sess.span_err(
- span,
- "linking modifier `bundle` is only compatible with \
- `static` linking kind",
- );
+ sess.emit_err(BundleNeedsStatic { span });
}
("verbatim", _) => {
assign_modifier(whole_archive)
}
("whole-archive", _) => {
- sess.span_err(
- span,
- "linking modifier `whole-archive` is only compatible with \
- `static` linking kind",
- );
+ sess.emit_err(WholeArchiveNeedsStatic { span });
}
("as-needed", Some(NativeLibKind::Dylib { as_needed }))
assign_modifier(as_needed)
}
("as-needed", _) => {
- sess.span_err(
- span,
- "linking modifier `as-needed` is only compatible with \
- `dylib` and `framework` linking kinds",
- );
+ sess.emit_err(AsNeededCompatibility { span });
}
_ => {
- sess.span_err(
- span,
- format!(
- "unknown linking modifier `{modifier}`, expected one of: \
- bundle, verbatim, whole-archive, as-needed"
- ),
- );
+ sess.emit_err(UnknownLinkModifier { span, modifier });
}
}
}
if let Some((_, span)) = wasm_import_module {
if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
- let msg = "`wasm_import_module` is incompatible with \
- other arguments in `#[link]` attributes";
- sess.span_err(span, msg);
+ sess.emit_err(IncompatibleWasmLink { span });
}
} else if name.is_none() {
- struct_span_err!(
- sess,
- m.span,
- E0459,
- "`#[link]` attribute requires a `name = \"string\"` argument"
- )
- .span_label(m.span, "missing `name` argument")
- .emit();
+ sess.emit_err(LinkRequiresName { span: m.span });
}
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
if let Some((_, span)) = import_name_type {
if kind != Some(NativeLibKind::RawDylib) {
- let msg = "import name type can only be used with link kind `raw-dylib`";
- sess.span_err(span, msg);
+ sess.emit_err(ImportNameTypeRaw { span });
}
}
let dll_imports = match kind {
Some(NativeLibKind::RawDylib) => {
if let Some((name, span)) = name && name.as_str().contains('\0') {
- sess.span_err(
- span,
- "link name must not contain NUL characters if link kind is `raw-dylib`",
- );
+ sess.emit_err(RawDylibNoNul { span });
}
foreign_mod_items
.iter()
.iter()
.find(|a| a.has_name(sym::link_ordinal))
.unwrap();
- sess.span_err(
- link_ordinal_attr.span,
- "`#[link_ordinal]` is only supported if link kind is `raw-dylib`",
- );
+ sess.emit_err(LinkOrdinalRawDylib { span: link_ordinal_attr.span });
}
}
for lib in &self.tcx.sess.opts.libs {
if let NativeLibKind::Framework { .. } = lib.kind && !self.tcx.sess.target.is_like_osx {
// Cannot check this when parsing options because the target is not yet available.
- self.tcx.sess.err("library kind `framework` is only supported on Apple targets");
+ self.tcx.sess.emit_err(LibFrameworkApple);
}
if let Some(ref new_name) = lib.new_name {
let any_duplicate = self
.filter_map(|lib| lib.name.as_ref())
.any(|n| n.as_str() == lib.name);
if new_name.is_empty() {
- self.tcx.sess.err(format!(
- "an empty renaming target was specified for library `{}`",
- lib.name
- ));
+ self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: &lib.name });
} else if !any_duplicate {
- self.tcx.sess.err(format!(
- "renaming of the library `{}` was specified, \
- however this crate contains no `#[link(...)]` \
- attributes referencing this library",
- lib.name
- ));
+ self.tcx.sess.emit_err(RenamingNoLink { lib_name: &lib.name });
} else if !renames.insert(&lib.name) {
- self.tcx.sess.err(format!(
- "multiple renamings were \
- specified for library `{}`",
- lib.name
- ));
+ self.tcx.sess.emit_err(MultipleRenamings { lib_name: &lib.name });
}
}
}
// involved or not, library reordering and kind overriding without
// explicit `:rename` in particular.
if lib.has_modifiers() || passed_lib.has_modifiers() {
- let msg = "overriding linking modifiers from command line is not supported";
match lib.foreign_module {
- Some(def_id) => self.tcx.sess.span_err(self.tcx.def_span(def_id), msg),
- None => self.tcx.sess.err(msg),
+ Some(def_id) => self.tcx.sess.emit_err(NoLinkModOverride {
+ span: Some(self.tcx.def_span(def_id)),
+ }),
+ None => {
+ self.tcx.sess.emit_err(NoLinkModOverride { span: None })
+ }
};
}
if passed_lib.kind != NativeLibKind::Unspecified {
DllCallingConvention::Vectorcall(self.i686_arg_list_size(item))
}
_ => {
- self.tcx.sess.span_fatal(
- item.span,
- r#"ABI not supported by `#[link(kind = "raw-dylib")]` on i686"#,
- );
+ self.tcx.sess.emit_fatal(UnsupportedAbiI686 { span: item.span });
}
}
} else {
match abi {
Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C,
_ => {
- self.tcx.sess.span_fatal(
- item.span,
- r#"ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture"#,
- );
+ self.tcx.sess.emit_fatal(UnsupportedAbi { span: item.span });
}
}
};
+use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile};
use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
use crate::rmeta::table::TableBuilder;
use crate::rmeta::*;
if should_encode_type(tcx, local_id, def_kind) {
record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
}
- if let DefKind::TyParam | DefKind::ConstParam = def_kind {
- if let Some(default) = self.tcx.object_lifetime_default(def_id) {
- record!(self.tables.object_lifetime_default[def_id] <- default);
- }
+ if let DefKind::TyParam = def_kind {
+ let default = self.tcx.object_lifetime_default(def_id);
+ record!(self.tables.object_lifetime_default[def_id] <- default);
}
if let DefKind::Trait | DefKind::TraitAlias = def_kind {
record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
let tcx = self.tcx;
- let keys_and_jobs = tcx
- .mir_keys(())
- .iter()
- .filter_map(|&def_id| {
- let (encode_const, encode_opt) = should_encode_mir(tcx, def_id);
- if encode_const || encode_opt {
- Some((def_id, encode_const, encode_opt))
- } else {
- None
- }
- })
- .collect::<Vec<_>>();
- for (def_id, encode_const, encode_opt) in keys_and_jobs.into_iter() {
+ let keys_and_jobs = tcx.mir_keys(()).iter().filter_map(|&def_id| {
+ let (encode_const, encode_opt) = should_encode_mir(tcx, def_id);
+ if encode_const || encode_opt { Some((def_id, encode_const, encode_opt)) } else { None }
+ });
+ for (def_id, encode_const, encode_opt) in keys_and_jobs {
debug_assert!(encode_const || encode_opt);
debug!("EntryBuilder::encode_mir({:?})", def_id);
fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
let mut encoder = opaque::FileEncoder::new(path)
- .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to create file encoder: {}", err)));
+ .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err }));
encoder.emit_raw_bytes(METADATA_HEADER);
// Will be filled with the root position after encoding everything.
// Encode the root position.
let header = METADATA_HEADER.len();
file.seek(std::io::SeekFrom::Start(header as u64))
- .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to seek the file: {}", err)));
+ .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err }));
let pos = root.position.get();
file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])
- .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to write to the file: {}", err)));
+ .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err }));
// Return to the position where we are before writing the root position.
file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap();
Some(def_kind)
}
+ /// Finds the id of the parent node to this one.
+ ///
+ /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`].
pub fn find_parent_node(self, id: HirId) -> Option<HirId> {
if id.local_id == ItemLocalId::from_u32(0) {
Some(self.tcx.hir_owner_parent(id.owner))
query is_late_bound_map(_: LocalDefId) -> Option<&'tcx FxIndexSet<LocalDefId>> {
desc { "testing if a region is late bound" }
}
- /// For a given item (like a struct), gets the default lifetimes to be used
+ /// For a given item's generic parameter, gets the default lifetimes to be used
/// for each parameter if a trait object were to be passed for that parameter.
- /// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`.
- /// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`.
- query object_lifetime_default(key: DefId) -> Option<ObjectLifetimeDefault> {
- desc { "looking up lifetime defaults for generic parameter `{:?}`", key }
+ /// For example, for `T` in `struct Foo<'a, T>`, this would be `'static`.
+ /// For `T` in `struct Foo<'a, T: 'a>`, this would instead be `'a`.
+ /// This query will panic if passed something that is not a type parameter.
+ query object_lifetime_default(key: DefId) -> ObjectLifetimeDefault {
+ desc { "looking up lifetime defaults for generic parameter `{}`", tcx.def_path_str(key) }
separate_provide_extern
}
query late_bound_vars_map(_: LocalDefId)
/// `let <PAT> = ...`
///
/// If a type annotation is included, it is added as an ascription pattern.
- pattern: Pat<'tcx>,
+ pattern: Box<Pat<'tcx>>,
/// `let pat: ty = <INIT>`
initializer: Option<ExprId>,
},
Let {
expr: ExprId,
- pat: Pat<'tcx>,
+ pat: Box<Pat<'tcx>>,
},
/// A `match` expression.
Match {
/// A `match` arm.
#[derive(Clone, Debug, HashStable)]
pub struct Arm<'tcx> {
- pub pattern: Pat<'tcx>,
+ pub pattern: Box<Pat<'tcx>>,
pub guard: Option<Guard<'tcx>>,
pub body: ExprId,
pub lint_level: LintLevel,
#[derive(Clone, Debug, HashStable)]
pub enum Guard<'tcx> {
If(ExprId),
- IfLet(Pat<'tcx>, ExprId),
+ IfLet(Box<Pat<'tcx>>, ExprId),
}
#[derive(Copy, Clone, Debug, HashStable)]
#[derive(Clone, Debug, HashStable)]
pub struct FieldPat<'tcx> {
pub field: Field,
- pub pattern: Pat<'tcx>,
+ pub pattern: Box<Pat<'tcx>>,
}
#[derive(Clone, Debug, HashStable)]
pub struct Pat<'tcx> {
pub ty: Ty<'tcx>,
pub span: Span,
- pub kind: Box<PatKind<'tcx>>,
+ pub kind: PatKind<'tcx>,
}
impl<'tcx> Pat<'tcx> {
pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
- Pat { ty, span: DUMMY_SP, kind: Box::new(PatKind::Wild) }
+ Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
}
}
AscribeUserType {
ascription: Ascription<'tcx>,
- subpattern: Pat<'tcx>,
+ subpattern: Box<Pat<'tcx>>,
},
/// `x`, `ref x`, `x @ P`, etc.
mode: BindingMode,
var: LocalVarId,
ty: Ty<'tcx>,
- subpattern: Option<Pat<'tcx>>,
+ subpattern: Option<Box<Pat<'tcx>>>,
/// Is this the leftmost occurrence of the binding, i.e., is `var` the
/// `HirId` of this pattern?
is_primary: bool,
/// `box P`, `&P`, `&mut P`, etc.
Deref {
- subpattern: Pat<'tcx>,
+ subpattern: Box<Pat<'tcx>>,
},
/// One of the following:
value: mir::ConstantKind<'tcx>,
},
- Range(PatRange<'tcx>),
+ Range(Box<PatRange<'tcx>>),
/// Matches against a slice, checking the length and extracting elements.
/// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
/// e.g., `&[ref xs @ ..]`.
Slice {
- prefix: Vec<Pat<'tcx>>,
- slice: Option<Pat<'tcx>>,
- suffix: Vec<Pat<'tcx>>,
+ prefix: Box<[Box<Pat<'tcx>>]>,
+ slice: Option<Box<Pat<'tcx>>>,
+ suffix: Box<[Box<Pat<'tcx>>]>,
},
/// Fixed match against an array; irrefutable.
Array {
- prefix: Vec<Pat<'tcx>>,
- slice: Option<Pat<'tcx>>,
- suffix: Vec<Pat<'tcx>>,
+ prefix: Box<[Box<Pat<'tcx>>]>,
+ slice: Option<Box<Pat<'tcx>>>,
+ suffix: Box<[Box<Pat<'tcx>>]>,
},
/// An or-pattern, e.g. `p | q`.
/// Invariant: `pats.len() >= 2`.
Or {
- pats: Vec<Pat<'tcx>>,
+ pats: Box<[Box<Pat<'tcx>>]>,
},
}
-#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
+#[derive(Clone, Debug, PartialEq, HashStable)]
pub struct PatRange<'tcx> {
pub lo: mir::ConstantKind<'tcx>,
pub hi: mir::ConstantKind<'tcx>,
};
let mut start_or_comma = || start_or_continue(", ");
- match *self.kind {
+ match self.kind {
PatKind::Wild => write!(f, "_"),
PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern),
PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
Ok(())
}
PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
- let variant = match *self.kind {
+ let variant = match self.kind {
PatKind::Variant { adt_def, variant_index, .. } => {
Some(adt_def.variant(variant_index))
}
let mut printed = 0;
for p in subpatterns {
- if let PatKind::Wild = *p.pattern.kind {
+ if let PatKind::Wild = p.pattern.kind {
continue;
}
let name = variant.fields[p.field.index()].name;
write!(f, "{}", subpattern)
}
PatKind::Constant { value } => write!(f, "{}", value),
- PatKind::Range(PatRange { lo, hi, end }) => {
+ PatKind::Range(box PatRange { lo, hi, end }) => {
write!(f, "{}", lo)?;
write!(f, "{}", end)?;
write!(f, "{}", hi)
PatKind::Slice { ref prefix, ref slice, ref suffix }
| PatKind::Array { ref prefix, ref slice, ref suffix } => {
write!(f, "[")?;
- for p in prefix {
+ for p in prefix.iter() {
write!(f, "{}{}", start_or_comma(), p)?;
}
if let Some(ref slice) = *slice {
write!(f, "{}", start_or_comma())?;
- match *slice.kind {
+ match slice.kind {
PatKind::Wild => {}
_ => write!(f, "{}", slice)?,
}
write!(f, "..")?;
}
- for p in suffix {
+ for p in suffix.iter() {
write!(f, "{}{}", start_or_comma(), p)?;
}
write!(f, "]")
}
PatKind::Or { ref pats } => {
- for pat in pats {
+ for pat in pats.iter() {
write!(f, "{}{}", start_or_continue(" | "), pat)?;
}
Ok(())
static_assert_size!(Block, 56);
static_assert_size!(Expr<'_>, 64);
static_assert_size!(ExprKind<'_>, 40);
- static_assert_size!(Pat<'_>, 24);
- static_assert_size!(PatKind<'_>, 112);
- static_assert_size!(Stmt<'_>, 72);
- static_assert_size!(StmtKind<'_>, 64);
+ static_assert_size!(Pat<'_>, 72);
+ static_assert_size!(PatKind<'_>, 56);
+ static_assert_size!(Stmt<'_>, 56);
+ static_assert_size!(StmtKind<'_>, 48);
}
pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
use PatKind::*;
- match pat.kind.as_ref() {
+ match &pat.kind {
AscribeUserType { subpattern, ascription: _ }
| Deref { subpattern }
| Binding {
Constant { value: _ } => {}
Range(_) => {}
Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
- for subpattern in prefix {
+ for subpattern in prefix.iter() {
visitor.visit_pat(&subpattern);
}
if let Some(pat) = slice {
- visitor.visit_pat(pat);
+ visitor.visit_pat(&pat);
}
- for subpattern in suffix {
+ for subpattern in suffix.iter() {
visitor.visit_pat(&subpattern);
}
}
Or { pats } => {
- for pat in pats {
+ for pat in pats.iter() {
visitor.visit_pat(&pat);
}
}
pub promoted: P,
}
+impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ format!("{:?}", self).into_diagnostic_arg()
+ }
+}
+
impl<'tcx> Unevaluated<'tcx> {
#[inline]
pub fn shrink(self) -> Unevaluated<'tcx, ()> {
/// `ValTree` does not have this problem with representation, as it only contains integers or
/// lists of (nested) `ValTree`.
pub enum ValTree<'tcx> {
- /// ZSTs, integers, `bool`, `char` are represented as scalars.
+ /// integers, `bool`, `char` are represented as scalars.
/// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values
/// of these types have the same representation.
Leaf(ScalarInt),
// dont use SliceOrStr for now
/// The fields of any kind of aggregate. Structs, tuples and arrays are represented by
/// listing their fields' values in order.
+ ///
/// Enums are represented by storing their discriminant as a field, followed by all
/// the fields of the variant.
+ ///
+ /// ZST types are represented as an empty slice.
Branch(&'tcx [ValTree<'tcx>]),
}
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct CanonicalUserTypeAnnotation<'tcx> {
- pub user_ty: CanonicalUserType<'tcx>,
+ pub user_ty: Box<CanonicalUserType<'tcx>>,
pub span: Span,
pub inferred_ty: Ty<'tcx>,
}
Ok(layout)
}
+#[derive(Clone, Copy)]
pub struct LayoutCx<'tcx, C> {
pub tcx: C,
pub param_env: ty::ParamEnv<'tcx>,
)
}
+// Handle safe Rust thin and fat pointers.
+pub fn adjust_for_rust_scalar<'tcx>(
+ cx: LayoutCx<'tcx, TyCtxt<'tcx>>,
+ attrs: &mut ArgAttributes,
+ scalar: Scalar,
+ layout: TyAndLayout<'tcx>,
+ offset: Size,
+ is_return: bool,
+) {
+ // Booleans are always a noundef i1 that needs to be zero-extended.
+ if scalar.is_bool() {
+ attrs.ext(ArgExtension::Zext);
+ attrs.set(ArgAttribute::NoUndef);
+ return;
+ }
+
+ // Scalars which have invalid values cannot be undef.
+ if !scalar.is_always_valid(&cx) {
+ attrs.set(ArgAttribute::NoUndef);
+ }
+
+ // Only pointer types handled below.
+ let Scalar::Initialized { value: Pointer, valid_range} = scalar else { return };
+
+ if !valid_range.contains(0) {
+ attrs.set(ArgAttribute::NonNull);
+ }
+
+ if let Some(pointee) = layout.pointee_info_at(&cx, offset) {
+ if let Some(kind) = pointee.safe {
+ attrs.pointee_align = Some(pointee.align);
+
+ // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
+ // for the entire duration of the function as they can be deallocated
+ // at any time. Same for shared mutable references. If LLVM had a
+ // way to say "dereferenceable on entry" we could use it here.
+ attrs.pointee_size = match kind {
+ PointerKind::UniqueBorrowed
+ | PointerKind::UniqueBorrowedPinned
+ | PointerKind::Frozen => pointee.size,
+ PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
+ };
+
+ // `Box`, `&T`, and `&mut T` cannot be undef.
+ // Note that this only applies to the value of the pointer itself;
+ // this attribute doesn't make it UB for the pointed-to data to be undef.
+ attrs.set(ArgAttribute::NoUndef);
+
+ // The aliasing rules for `Box<T>` are still not decided, but currently we emit
+ // `noalias` for it. This can be turned off using an unstable flag.
+ // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
+ let noalias_for_box = cx.tcx.sess.opts.unstable_opts.box_noalias.unwrap_or(true);
+
+ // `&mut` pointer parameters never alias other parameters,
+ // or mutable global data
+ //
+ // `&T` where `T` contains no `UnsafeCell<U>` is immutable,
+ // and can be marked as both `readonly` and `noalias`, as
+ // LLVM's definition of `noalias` is based solely on memory
+ // dependencies rather than pointer equality
+ //
+ // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
+ // for UniqueBorrowed arguments, so that the codegen backend can decide whether
+ // or not to actually emit the attribute. It can also be controlled with the
+ // `-Zmutable-noalias` debugging option.
+ let no_alias = match kind {
+ PointerKind::SharedMutable
+ | PointerKind::UniqueBorrowed
+ | PointerKind::UniqueBorrowedPinned => false,
+ PointerKind::UniqueOwned => noalias_for_box,
+ PointerKind::Frozen => !is_return,
+ };
+ if no_alias {
+ attrs.set(ArgAttribute::NoAlias);
+ }
+
+ if kind == PointerKind::Frozen && !is_return {
+ attrs.set(ArgAttribute::ReadOnly);
+ }
+
+ if kind == PointerKind::UniqueBorrowed && !is_return {
+ attrs.set(ArgAttribute::NoAliasMutRef);
+ }
+ }
+ }
+}
+
impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
// FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
// arguments of this method, into a separate `struct`.
use SpecAbi::*;
let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall);
- // Handle safe Rust thin and fat pointers.
- let adjust_for_rust_scalar = |attrs: &mut ArgAttributes,
- scalar: Scalar,
- layout: TyAndLayout<'tcx>,
- offset: Size,
- is_return: bool| {
- // Booleans are always a noundef i1 that needs to be zero-extended.
- if scalar.is_bool() {
- attrs.ext(ArgExtension::Zext);
- attrs.set(ArgAttribute::NoUndef);
- return;
- }
-
- // Scalars which have invalid values cannot be undef.
- if !scalar.is_always_valid(self) {
- attrs.set(ArgAttribute::NoUndef);
- }
-
- // Only pointer types handled below.
- let Scalar::Initialized { value: Pointer, valid_range} = scalar else { return };
-
- if !valid_range.contains(0) {
- attrs.set(ArgAttribute::NonNull);
- }
-
- if let Some(pointee) = layout.pointee_info_at(self, offset) {
- if let Some(kind) = pointee.safe {
- attrs.pointee_align = Some(pointee.align);
-
- // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
- // for the entire duration of the function as they can be deallocated
- // at any time. Same for shared mutable references. If LLVM had a
- // way to say "dereferenceable on entry" we could use it here.
- attrs.pointee_size = match kind {
- PointerKind::UniqueBorrowed
- | PointerKind::UniqueBorrowedPinned
- | PointerKind::Frozen => pointee.size,
- PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
- };
-
- // `Box`, `&T`, and `&mut T` cannot be undef.
- // Note that this only applies to the value of the pointer itself;
- // this attribute doesn't make it UB for the pointed-to data to be undef.
- attrs.set(ArgAttribute::NoUndef);
-
- // The aliasing rules for `Box<T>` are still not decided, but currently we emit
- // `noalias` for it. This can be turned off using an unstable flag.
- // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
- let noalias_for_box =
- self.tcx().sess.opts.unstable_opts.box_noalias.unwrap_or(true);
-
- // `&mut` pointer parameters never alias other parameters,
- // or mutable global data
- //
- // `&T` where `T` contains no `UnsafeCell<U>` is immutable,
- // and can be marked as both `readonly` and `noalias`, as
- // LLVM's definition of `noalias` is based solely on memory
- // dependencies rather than pointer equality
- //
- // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
- // for UniqueBorrowed arguments, so that the codegen backend can decide whether
- // or not to actually emit the attribute. It can also be controlled with the
- // `-Zmutable-noalias` debugging option.
- let no_alias = match kind {
- PointerKind::SharedMutable
- | PointerKind::UniqueBorrowed
- | PointerKind::UniqueBorrowedPinned => false,
- PointerKind::UniqueOwned => noalias_for_box,
- PointerKind::Frozen => !is_return,
- };
- if no_alias {
- attrs.set(ArgAttribute::NoAlias);
- }
-
- if kind == PointerKind::Frozen && !is_return {
- attrs.set(ArgAttribute::ReadOnly);
- }
-
- if kind == PointerKind::UniqueBorrowed && !is_return {
- attrs.set(ArgAttribute::NoAliasMutRef);
- }
- }
- }
- };
-
let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
let is_return = arg_idx.is_none();
let mut arg = ArgAbi::new(self, layout, |layout, scalar, offset| {
let mut attrs = ArgAttributes::new();
- adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return);
+ adjust_for_rust_scalar(*self, &mut attrs, scalar, *layout, offset, is_return);
attrs
});
pub label_res_map: NodeMap<ast::NodeId>,
/// Resolutions for lifetimes.
pub lifetimes_res_map: NodeMap<LifetimeRes>,
- /// Mapping from generics `def_id`s to TAIT generics `def_id`s.
- /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
- /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
- /// field from the original parameter 'a to the new parameter 'a1.
- pub generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
/// Lifetime parameters that lowering will have to introduce.
pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, LifetimeRes)>>,
}
}
+impl rustc_errors::IntoDiagnosticArg for PolyTraitRef<'_> {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
/// An existential reference to a trait, where `Self` is erased.
/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
/// ```ignore (illustrative)
lint_level,
else_block,
} => {
- let ignores_expr_result = matches!(*pattern.kind, PatKind::Wild);
+ let ignores_expr_result = matches!(pattern.kind, PatKind::Wild);
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
// Enter the remainder scope, i.e., the bindings' destruction scope.
ArmHasGuard(false),
Some((None, initializer_span)),
);
- this.expr_into_pattern(block, pattern.clone(), init) // irrefutable pattern
+ this.expr_into_pattern(block, pattern, init) // irrefutable pattern
}
})
},
Constant { span, user_ty: None, literal }
}
ExprKind::NonHirLiteral { lit, ref user_ty } => {
- let user_ty = user_ty.as_ref().map(|box user_ty| {
+ let user_ty = user_ty.as_ref().map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
- user_ty: *user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: ty,
})
});
Constant { span, user_ty: user_ty, literal }
}
ExprKind::ZstLiteral { ref user_ty } => {
- let user_ty = user_ty.as_ref().map(|box user_ty| {
+ let user_ty = user_ty.as_ref().map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
- user_ty: *user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: ty,
})
});
Constant { span, user_ty: user_ty, literal }
}
ExprKind::NamedConst { def_id, substs, ref user_ty } => {
- let user_ty = user_ty.as_ref().map(|box user_ty| {
+ let user_ty = user_ty.as_ref().map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
- user_ty: *user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: ty,
})
});
fake_borrow_temps,
)
);
- if let Some(box user_ty) = user_ty {
+ if let Some(user_ty) = user_ty {
let annotation_index =
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span: source_info.span,
- user_ty: *user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: expr.ty,
});
let source = &this.thir[source];
let temp =
unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability));
- if let Some(box user_ty) = user_ty {
+ if let Some(user_ty) = user_ty {
let annotation_index =
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span: source_info.span,
- user_ty: *user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: expr.ty,
});
this.cfg.push(
};
let inferred_ty = expr.ty;
- let user_ty = user_ty.as_ref().map(|box user_ty| {
+ let user_ty = user_ty.as_ref().map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span: source_info.span,
- user_ty: *user_ty,
+ user_ty: user_ty.clone(),
inferred_ty,
})
});
pub(super) fn expr_into_pattern(
&mut self,
mut block: BasicBlock,
- irrefutable_pat: Pat<'tcx>,
+ irrefutable_pat: &Pat<'tcx>,
initializer: &Expr<'tcx>,
) -> BlockAnd<()> {
- match *irrefutable_pat.kind {
+ match irrefutable_pat.kind {
// Optimize the case of `let x = ...` to write directly into `x`
PatKind::Binding { mode: BindingMode::ByValue, var, subpattern: None, .. } => {
let place =
// broken.
PatKind::AscribeUserType {
subpattern:
- Pat {
+ box Pat {
kind:
- box PatKind::Binding {
- mode: BindingMode::ByValue,
- var,
- subpattern: None,
- ..
+ PatKind::Binding {
+ mode: BindingMode::ByValue, var, subpattern: None, ..
},
..
},
- ascription: thir::Ascription { annotation, variance: _ },
+ ascription: thir::Ascription { ref annotation, variance: _ },
} => {
let place =
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
let ty_source_info = self.source_info(annotation.span);
- let base = self.canonical_user_type_annotations.push(annotation);
+ let base = self.canonical_user_type_annotations.push(annotation.clone());
self.cfg.push(
block,
Statement {
pub(crate) fn place_into_pattern(
&mut self,
block: BasicBlock,
- irrefutable_pat: Pat<'tcx>,
+ irrefutable_pat: &Pat<'tcx>,
initializer: PlaceBuilder<'tcx>,
set_match_place: bool,
) -> BlockAnd<()> {
"visit_primary_bindings: pattern={:?} pattern_user_ty={:?}",
pattern, pattern_user_ty
);
- match *pattern.kind {
+ match pattern.kind {
PatKind::Binding {
mutability,
name,
| PatKind::Slice { ref prefix, ref slice, ref suffix } => {
let from = u64::try_from(prefix.len()).unwrap();
let to = u64::try_from(suffix.len()).unwrap();
- for subpattern in prefix {
+ for subpattern in prefix.iter() {
self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
}
for subpattern in slice {
f,
);
}
- for subpattern in suffix {
+ for subpattern in suffix.iter() {
self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
}
}
// may not all be in the leftmost subpattern. For example in
// `let (x | y) = ...`, the primary binding of `y` occurs in
// the right subpattern
- for subpattern in pats {
+ for subpattern in pats.iter() {
self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f);
}
}
},
/// Test whether the value falls within an inclusive or exclusive range
- Range(PatRange<'tcx>),
+ Range(Box<PatRange<'tcx>>),
/// Test that the length of the slice is equal to `len`.
Len { len: u64, op: BinOp },
// All of the or-patterns have been sorted to the end, so if the first
// pattern is an or-pattern we only have or-patterns.
- match *first_candidate.match_pairs[0].pattern.kind {
+ match first_candidate.match_pairs[0].pattern.kind {
PatKind::Or { .. } => (),
_ => {
self.test_candidates(
let mut otherwise = None;
for match_pair in match_pairs {
- let PatKind::Or { ref pats } = &*match_pair.pattern.kind else {
+ let PatKind::Or { ref pats } = &match_pair.pattern.kind else {
bug!("Or-patterns should have been sorted to the end");
};
let or_span = match_pair.pattern.span;
&mut self,
candidate: &mut Candidate<'pat, 'tcx>,
otherwise: &mut Option<BasicBlock>,
- pats: &'pat [Pat<'tcx>],
+ pats: &'pat [Box<Pat<'tcx>>],
or_span: Span,
place: PlaceBuilder<'tcx>,
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
let else_block_span = self.thir[else_block].span;
let (matching, failure) = self.in_if_then_scope(remainder_scope, |this| {
let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span));
- let pat = Pat { ty: init.ty, span: else_block_span, kind: Box::new(PatKind::Wild) };
+ let pat = Pat { ty: init.ty, span: else_block_span, kind: PatKind::Wild };
let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false);
this.declare_bindings(
visibility_scope,
loop {
let match_pairs = mem::take(&mut candidate.match_pairs);
- if let [MatchPair { pattern: Pat { kind: box PatKind::Or { pats }, .. }, place }] =
+ if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] =
&*match_pairs
{
existing_bindings.extend_from_slice(&new_bindings);
// late as possible.
candidate
.match_pairs
- .sort_by_key(|pair| matches!(*pair.pattern.kind, PatKind::Or { .. }));
+ .sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
debug!(simplified = ?candidate, "simplify_candidate");
return false; // if we were not able to simplify any, done.
}
&mut self,
candidate: &Candidate<'pat, 'tcx>,
place: PlaceBuilder<'tcx>,
- pats: &'pat [Pat<'tcx>],
+ pats: &'pat [Box<Pat<'tcx>>],
) -> Vec<Candidate<'pat, 'tcx>> {
pats.iter()
- .map(|pat| {
+ .map(|box pat| {
let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard);
self.simplify_candidate(&mut candidate);
candidate
candidate: &mut Candidate<'pat, 'tcx>,
) -> Result<(), MatchPair<'pat, 'tcx>> {
let tcx = self.tcx;
- match *match_pair.pattern.kind {
+ match match_pair.pattern.kind {
PatKind::AscribeUserType {
ref subpattern,
ascription: thir::Ascription { ref annotation, variance },
Err(match_pair)
}
- PatKind::Range(PatRange { lo, hi, end }) => {
+ PatKind::Range(box PatRange { lo, hi, end }) => {
let (range, bias) = match *lo.ty().kind() {
ty::Char => {
(Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0)
&mut candidate.match_pairs,
&match_pair.place,
prefix,
- slice.as_ref(),
+ slice,
suffix,
);
Ok(())
&mut candidate.match_pairs,
&match_pair.place,
prefix,
- slice.as_ref(),
+ slice,
suffix,
);
Ok(())
///
/// It is a bug to call this with a not-fully-simplified pattern.
pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
- match *match_pair.pattern.kind {
+ match match_pair.pattern.kind {
PatKind::Variant { adt_def, substs: _, variant_index: _, subpatterns: _ } => Test {
span: match_pair.pattern.span,
kind: TestKind::Switch {
kind: TestKind::Eq { value, ty: match_pair.pattern.ty },
},
- PatKind::Range(range) => {
+ PatKind::Range(ref range) => {
assert_eq!(range.lo.ty(), match_pair.pattern.ty);
assert_eq!(range.hi.ty(), match_pair.pattern.ty);
- Test { span: match_pair.pattern.span, kind: TestKind::Range(range) }
+ Test { span: match_pair.pattern.span, kind: TestKind::Range(range.clone()) }
}
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
return false;
};
- match *match_pair.pattern.kind {
+ match match_pair.pattern.kind {
PatKind::Constant { value } => {
options
.entry(value)
PatKind::Variant { .. } => {
panic!("you should have called add_variants_to_switch instead!");
}
- PatKind::Range(range) => {
+ PatKind::Range(ref range) => {
// Check that none of the switch values are in the range.
- self.values_not_contained_in_range(range, options).unwrap_or(false)
+ self.values_not_contained_in_range(&*range, options).unwrap_or(false)
}
PatKind::Slice { .. }
| PatKind::Array { .. }
return false;
};
- match *match_pair.pattern.kind {
+ match match_pair.pattern.kind {
PatKind::Variant { adt_def: _, variant_index, .. } => {
// We have a pattern testing for variant `variant_index`
// set the corresponding index to true
}
}
- TestKind::Range(PatRange { lo, hi, ref end }) => {
+ TestKind::Range(box PatRange { lo, hi, ref end }) => {
let lower_bound_success = self.cfg.start_new_block();
let target_blocks = make_target_blocks(self);
let (match_pair_index, match_pair) =
candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == *test_place)?;
- match (&test.kind, &*match_pair.pattern.kind) {
+ match (&test.kind, &match_pair.pattern.kind) {
// If we are performing a variant switch, then this
// informs variant patterns, but nothing else.
(
Some(index)
}
- (&TestKind::SwitchInt { switch_ty: _, ref options }, &PatKind::Range(range)) => {
+ (&TestKind::SwitchInt { switch_ty: _, ref options }, &PatKind::Range(ref range)) => {
let not_contained =
- self.values_not_contained_in_range(range, options).unwrap_or(false);
+ self.values_not_contained_in_range(&*range, options).unwrap_or(false);
if not_contained {
// No switch values are contained in the pattern range,
match_pair_index,
candidate,
prefix,
- slice.as_ref(),
+ slice,
suffix,
);
Some(0)
match_pair_index,
candidate,
prefix,
- slice.as_ref(),
+ slice,
suffix,
);
Some(0)
}
}
- (&TestKind::Range(test), &PatKind::Range(pat)) => {
+ (&TestKind::Range(ref test), &PatKind::Range(ref pat)) => {
use std::cmp::Ordering::*;
if test == pat {
no_overlap
}
- (&TestKind::Range(range), &PatKind::Constant { value }) => {
- if let Some(false) = self.const_range_contains(range, value) {
+ (&TestKind::Range(ref range), &PatKind::Constant { value }) => {
+ if let Some(false) = self.const_range_contains(&*range, value) {
// `value` is not contained in the testing range,
// so `value` can be matched only if this test fails.
Some(1)
// However, at this point we can still encounter or-patterns that were extracted
// from previous calls to `sort_candidate`, so we need to manually address that
// case to avoid panicking in `self.test()`.
- if let PatKind::Or { .. } = &*match_pair.pattern.kind {
+ if let PatKind::Or { .. } = &match_pair.pattern.kind {
return None;
}
&mut self,
match_pair_index: usize,
candidate: &mut Candidate<'pat, 'tcx>,
- prefix: &'pat [Pat<'tcx>],
- opt_slice: Option<&'pat Pat<'tcx>>,
- suffix: &'pat [Pat<'tcx>],
+ prefix: &'pat [Box<Pat<'tcx>>],
+ opt_slice: &'pat Option<Box<Pat<'tcx>>>,
+ suffix: &'pat [Box<Pat<'tcx>>],
) {
let removed_place = candidate.match_pairs.remove(match_pair_index).place;
self.prefix_slice_suffix(
fn const_range_contains(
&self,
- range: PatRange<'tcx>,
+ range: &PatRange<'tcx>,
value: ConstantKind<'tcx>,
) -> Option<bool> {
use std::cmp::Ordering::*;
fn values_not_contained_in_range(
&self,
- range: PatRange<'tcx>,
+ range: &PatRange<'tcx>,
options: &FxIndexMap<ConstantKind<'tcx>, u128>,
) -> Option<bool> {
for &val in options.keys() {
&mut self,
match_pairs: &mut SmallVec<[MatchPair<'pat, 'tcx>; 1]>,
place: &PlaceBuilder<'tcx>,
- prefix: &'pat [Pat<'tcx>],
- opt_slice: Option<&'pat Pat<'tcx>>,
- suffix: &'pat [Pat<'tcx>],
+ prefix: &'pat [Box<Pat<'tcx>>],
+ opt_slice: &'pat Option<Box<Pat<'tcx>>>,
+ suffix: &'pat [Box<Pat<'tcx>>],
) {
let tcx = self.tcx;
let (min_length, exact_size) = if let Ok(place_resolved) =
let original_source_scope = self.source_scope;
let span = pattern.span;
self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span);
- match *pattern.kind {
+ match pattern.kind {
// Don't introduce extra copies for simple bindings
PatKind::Binding {
mutability,
Some((Some(&place), span)),
);
let place_builder = PlaceBuilder::from(local);
- unpack!(block = self.place_into_pattern(block, pattern, place_builder, false));
+ unpack!(
+ block =
+ self.place_into_pattern(block, pattern.as_ref(), place_builder, false)
+ );
}
}
self.source_scope = original_source_scope;
fn visit_pat(&mut self, pat: &Pat<'tcx>) {
if self.in_union_destructure {
- match *pat.kind {
+ match pat.kind {
// binding to a variable allows getting stuff out of variable
PatKind::Binding { .. }
// match is conditional on having this value
}
};
- match &*pat.kind {
+ match &pat.kind {
PatKind::Leaf { .. } => {
if let ty::Adt(adt_def, ..) = pat.ty.kind() {
if adt_def.is_union() {
{
debug!("mirror_stmts: user_ty={:?}", user_ty);
let annotation = CanonicalUserTypeAnnotation {
- user_ty,
+ user_ty: Box::new(user_ty),
span: ty.span,
inferred_ty: self.typeck_results.node_type(ty.hir_id),
};
- pattern = Pat {
+ pattern = Box::new(Pat {
ty: pattern.ty,
span: pattern.span,
- kind: Box::new(PatKind::AscribeUserType {
+ kind: PatKind::AscribeUserType {
ascription: Ascription {
annotation,
variance: ty::Variance::Covariant,
},
subpattern: pattern,
- }),
- };
+ },
+ });
}
}
let kind = match expr.kind {
// Here comes the interesting stuff:
- hir::ExprKind::MethodCall(segment, ref args, fn_span) => {
+ hir::ExprKind::MethodCall(segment, receiver, ref args, fn_span) => {
// Rewrite a.b(c) into UFCS form like Trait::b(a, c)
let expr = self.method_callee(expr, segment.ident.span, None);
// When we apply adjustments to the receiver, use the span of
// the overall method call for better diagnostics. args[0]
// is guaranteed to exist, since a method call always has a receiver.
- let old_adjustment_span = self.adjustment_span.replace((args[0].hir_id, expr_span));
+ let old_adjustment_span =
+ self.adjustment_span.replace((receiver.hir_id, expr_span));
info!("Using method span: {:?}", expr.span);
- let args = self.mirror_exprs(args);
+ let args = std::iter::once(receiver)
+ .chain(args.iter())
+ .map(|expr| self.mirror_expr(expr))
+ .collect();
self.adjustment_span = old_adjustment_span;
ExprKind::Call {
ty: expr.ty,
}
#[instrument(level = "debug", skip(self))]
- pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
+ pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Box<Pat<'tcx>> {
let p = match self.tcx.hir().get(p.hir_id) {
Node::Pat(p) => p,
node => bug!("pattern became {:?}", node),
id: hir::HirId,
span: Span,
mir_structural_match_violation: bool,
- ) -> Pat<'tcx> {
+ ) -> Box<Pat<'tcx>> {
self.tcx.infer_ctxt().enter(|infcx| {
let mut convert = ConstToPat::new(self, id, span, infcx);
convert.to_pat(cv, mir_structural_match_violation)
&mut self,
cv: mir::ConstantKind<'tcx>,
mir_structural_match_violation: bool,
- ) -> Pat<'tcx> {
+ ) -> Box<Pat<'tcx>> {
trace!(self.treat_byte_string_as_slice);
// This method is just a wrapper handling a validity check; the heavy lifting is
// performed by the recursive `recur` method, which is not meant to be
// level of indirection can be eliminated
let inlined_const_as_pat =
- self.recur(cv, mir_structural_match_violation).unwrap_or_else(|_| Pat {
- span: self.span,
- ty: cv.ty(),
- kind: Box::new(PatKind::Constant { value: cv }),
+ self.recur(cv, mir_structural_match_violation).unwrap_or_else(|_| {
+ Box::new(Pat {
+ span: self.span,
+ ty: cv.ty(),
+ kind: PatKind::Constant { value: cv },
+ })
});
if self.include_lint_checks && !self.saw_const_match_error.get() {
&self,
cv: mir::ConstantKind<'tcx>,
mir_structural_match_violation: bool,
- ) -> Result<Pat<'tcx>, FallbackToConstRef> {
+ ) -> Result<Box<Pat<'tcx>>, FallbackToConstRef> {
let id = self.id;
let span = self.span;
let tcx = self.tcx();
.map(|val| self.recur(*val, false))
.collect::<Result<_, _>>()?,
slice: None,
- suffix: Vec::new(),
+ suffix: Box::new([]),
},
ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
// These are not allowed and will error elsewhere anyway.
let old = self.behind_reference.replace(true);
let array = tcx.deref_mir_constant(self.param_env.and(cv));
let val = PatKind::Deref {
- subpattern: Pat {
- kind: Box::new(PatKind::Array {
+ subpattern: Box::new(Pat {
+ kind: PatKind::Array {
prefix: tcx
.destructure_mir_constant(param_env, array)
.fields
.map(|val| self.recur(*val, false))
.collect::<Result<_, _>>()?,
slice: None,
- suffix: vec![],
- }),
+ suffix: Box::new([]),
+ },
span,
ty: *pointee_ty,
- },
+ }),
};
self.behind_reference.set(old);
val
let old = self.behind_reference.replace(true);
let array = tcx.deref_mir_constant(self.param_env.and(cv));
let val = PatKind::Deref {
- subpattern: Pat {
- kind: Box::new(PatKind::Slice {
+ subpattern: Box::new(Pat {
+ kind: PatKind::Slice {
prefix: tcx
.destructure_mir_constant(param_env, array)
.fields
.map(|val| self.recur(*val, false))
.collect::<Result<_, _>>()?,
slice: None,
- suffix: vec![],
- }),
+ suffix: Box::new([]),
+ },
span,
ty: tcx.mk_slice(elem_ty),
- },
+ }),
};
self.behind_reference.set(old);
val
);
}
- Ok(Pat { span, ty: cv.ty(), kind: Box::new(kind) })
+ Ok(Box::new(Pat { span, ty: cv.ty(), kind }))
}
}
/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> {
fn expand<'p, 'tcx>(pat: &'p Pat<'tcx>, vec: &mut Vec<&'p Pat<'tcx>>) {
- if let PatKind::Or { pats } = pat.kind.as_ref() {
- for pat in pats {
- expand(pat, vec);
+ if let PatKind::Or { pats } = &pat.kind {
+ for pat in pats.iter() {
+ expand(&pat, vec);
}
} else {
vec.push(pat)
let kind = if lo == hi {
PatKind::Constant { value: lo_const }
} else {
- PatKind::Range(PatRange { lo: lo_const, hi: hi_const, end: RangeEnd::Included })
+ PatKind::Range(Box::new(PatRange {
+ lo: lo_const,
+ hi: hi_const,
+ end: RangeEnd::Included,
+ }))
};
- Pat { ty, span: DUMMY_SP, kind: Box::new(kind) }
+ Pat { ty, span: DUMMY_SP, kind }
}
/// Lint on likely incorrect range patterns (#63987)
let mkpat = |pat| DeconstructedPat::from_pat(cx, pat);
let ctor;
let fields;
- match pat.kind.as_ref() {
+ match &pat.kind {
PatKind::AscribeUserType { subpattern, .. } => return mkpat(subpattern),
PatKind::Binding { subpattern: Some(subpat), .. } => return mkpat(subpat),
PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
fields = Fields::singleton(cx, pat);
}
ty::Adt(adt, _) => {
- ctor = match pat.kind.as_ref() {
+ ctor = match pat.kind {
PatKind::Leaf { .. } => Single,
- PatKind::Variant { variant_index, .. } => Variant(*variant_index),
+ PatKind::Variant { variant_index, .. } => Variant(variant_index),
_ => bug!(),
};
let variant = &adt.variant(ctor.variant_index_for_adt(*adt));
}
}
}
- &PatKind::Range(PatRange { lo, hi, end }) => {
+ &PatKind::Range(box PatRange { lo, hi, end }) => {
let ty = lo.ty();
ctor = if let Some(int_range) = IntRange::from_range(
cx.tcx,
FixedLen(prefix.len() + suffix.len())
};
ctor = Slice(Slice::new(array_len, kind));
- fields = Fields::from_iter(cx, prefix.iter().chain(suffix).map(mkpat));
+ fields =
+ Fields::from_iter(cx, prefix.iter().chain(suffix.iter()).map(|p| mkpat(&*p)));
}
PatKind::Or { .. } => {
ctor = Or;
pub(crate) fn to_pat(&self, cx: &MatchCheckCtxt<'p, 'tcx>) -> Pat<'tcx> {
let is_wildcard = |pat: &Pat<'_>| {
- matches!(*pat.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild)
+ matches!(pat.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild)
};
- let mut subpatterns = self.iter_fields().map(|p| p.to_pat(cx));
- let pat = match &self.ctor {
+ let mut subpatterns = self.iter_fields().map(|p| Box::new(p.to_pat(cx)));
+ let kind = match &self.ctor {
Single | Variant(_) => match self.ty.kind() {
ty::Tuple(..) => PatKind::Leaf {
subpatterns: subpatterns
.enumerate()
- .map(|(i, p)| FieldPat { field: Field::new(i), pattern: p })
+ .map(|(i, pattern)| FieldPat { field: Field::new(i), pattern })
.collect(),
},
ty::Adt(adt_def, _) if adt_def.is_box() => {
FixedLen(_) => PatKind::Slice {
prefix: subpatterns.collect(),
slice: None,
- suffix: vec![],
+ suffix: Box::new([]),
},
VarLen(prefix, _) => {
let mut subpatterns = subpatterns.peekable();
subpatterns.next();
}
}
- let suffix: Vec<_> = subpatterns.collect();
+ let suffix: Box<[_]> = subpatterns.collect();
let wild = Pat::wildcard_from_ty(self.ty);
- PatKind::Slice { prefix, slice: Some(wild), suffix }
+ PatKind::Slice {
+ prefix: prefix.into_boxed_slice(),
+ slice: Some(Box::new(wild)),
+ suffix,
+ }
}
}
}
&Str(value) => PatKind::Constant { value },
- &FloatRange(lo, hi, end) => PatKind::Range(PatRange { lo, hi, end }),
+ &FloatRange(lo, hi, end) => PatKind::Range(Box::new(PatRange { lo, hi, end })),
IntRange(range) => return range.to_pat(cx.tcx, self.ty),
Wildcard | NonExhaustive => PatKind::Wild,
Missing { .. } => bug!(
}
};
- Pat { ty: self.ty, span: DUMMY_SP, kind: Box::new(pat) }
+ Pat { ty: self.ty, span: DUMMY_SP, kind }
}
pub(super) fn is_or_pat(&self) -> bool {
param_env: ty::ParamEnv<'tcx>,
typeck_results: &'a ty::TypeckResults<'tcx>,
pat: &'tcx hir::Pat<'tcx>,
-) -> Pat<'tcx> {
+) -> Box<Pat<'tcx>> {
let mut pcx = PatCtxt::new(tcx, param_env, typeck_results);
let result = pcx.lower_pattern(pat);
if !pcx.errors.is_empty() {
self
}
- pub(crate) fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
+ pub(crate) fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
// When implicit dereferences have been inserted in this pattern, the unadjusted lowered
// pattern has the type that results *after* dereferencing. For example, in this code:
//
let unadjusted_pat = self.lower_pattern_unadjusted(pat);
self.typeck_results.pat_adjustments().get(pat.hir_id).unwrap_or(&vec![]).iter().rev().fold(
unadjusted_pat,
- |pat, ref_ty| {
+ |pat: Box<_>, ref_ty| {
debug!("{:?}: wrapping pattern with type {:?}", pat, ref_ty);
- Pat {
+ Box::new(Pat {
span: pat.span,
ty: *ref_ty,
- kind: Box::new(PatKind::Deref { subpattern: pat }),
- }
+ kind: PatKind::Deref { subpattern: pat },
+ })
},
)
}
expr: &'tcx hir::Expr<'tcx>,
) -> (PatKind<'tcx>, Option<Ascription<'tcx>>) {
match self.lower_lit(expr) {
- PatKind::AscribeUserType { ascription, subpattern: Pat { kind: box kind, .. } } => {
+ PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => {
(kind, Some(ascription))
}
kind => (kind, None),
match (end, cmp) {
// `x..y` where `x < y`.
// Non-empty because the range includes at least `x`.
- (RangeEnd::Excluded, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }),
+ (RangeEnd::Excluded, Some(Ordering::Less)) => {
+ PatKind::Range(Box::new(PatRange { lo, hi, end }))
+ }
// `x..y` where `x >= y`. The range is empty => error.
(RangeEnd::Excluded, _) => {
struct_span_err!(
// `x..=y` where `x == y`.
(RangeEnd::Included, Some(Ordering::Equal)) => PatKind::Constant { value: lo },
// `x..=y` where `x < y`.
- (RangeEnd::Included, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }),
+ (RangeEnd::Included, Some(Ordering::Less)) => {
+ PatKind::Range(Box::new(PatRange { lo, hi, end }))
+ }
// `x..=y` where `x > y` hence the range is empty => error.
(RangeEnd::Included, _) => {
let mut err = struct_span_err!(
}
}
- fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
+ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
let mut ty = self.typeck_results.node_type(pat.hir_id);
let kind = match pat.kind {
// constants somewhere. Have them on the range pattern.
for end in &[lo, hi] {
if let Some((_, Some(ascription))) = end {
- let subpattern = Pat { span: pat.span, ty, kind: Box::new(kind) };
+ let subpattern = Box::new(Pat { span: pat.span, ty, kind });
kind =
PatKind::AscribeUserType { ascription: ascription.clone(), subpattern };
}
hir::PatKind::Or(ref pats) => PatKind::Or { pats: self.lower_patterns(pats) },
};
- Pat { span: pat.span, ty, kind: Box::new(kind) }
+ Box::new(Pat { span: pat.span, ty, kind })
}
fn lower_tuple_subpats(
.collect()
}
- fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Vec<Pat<'tcx>> {
+ fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Box<Pat<'tcx>>]> {
pats.iter().map(|p| self.lower_pattern(p)).collect()
}
- fn lower_opt_pattern(&mut self, pat: &'tcx Option<&'tcx hir::Pat<'tcx>>) -> Option<Pat<'tcx>> {
+ fn lower_opt_pattern(
+ &mut self,
+ pat: &'tcx Option<&'tcx hir::Pat<'tcx>>,
+ ) -> Option<Box<Pat<'tcx>>> {
pat.as_ref().map(|p| self.lower_pattern(p))
}
if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
let annotation = CanonicalUserTypeAnnotation {
- user_ty,
+ user_ty: Box::new(user_ty),
span,
inferred_ty: self.typeck_results.node_type(hir_id),
};
kind = PatKind::AscribeUserType {
- subpattern: Pat { span, ty, kind: Box::new(kind) },
+ subpattern: Box::new(Pat { span, ty, kind }),
ascription: Ascription { annotation, variance: ty::Variance::Covariant },
};
}
/// it to `const_to_pat`. Any other path (like enum variants without fields)
/// is converted to the corresponding pattern via `lower_variant_or_leaf`.
#[instrument(skip(self), level = "debug")]
- fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> Pat<'tcx> {
+ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> Box<Pat<'tcx>> {
let ty = self.typeck_results.node_type(id);
let res = self.typeck_results.qpath_res(qpath, id);
- let pat_from_kind = |kind| Pat { span, ty, kind: Box::new(kind) };
+ let pat_from_kind = |kind| Box::new(Pat { span, ty, kind });
let (def_id, is_associated_const) = match res {
Res::Def(DefKind::Const, def_id) => (def_id, false),
let user_provided_types = self.typeck_results().user_provided_types();
if let Some(&user_ty) = user_provided_types.get(id) {
let annotation = CanonicalUserTypeAnnotation {
- user_ty,
+ user_ty: Box::new(user_ty),
span,
inferred_ty: self.typeck_results().node_type(id),
};
- Pat {
+ Box::new(Pat {
span,
- kind: Box::new(PatKind::AscribeUserType {
+ kind: PatKind::AscribeUserType {
subpattern: pattern,
ascription: Ascription {
annotation,
/// `variance` field documentation for details.
variance: ty::Variance::Contravariant,
},
- }),
+ },
ty: const_.ty(),
- }
+ })
} else {
pattern
}
_ => bug!("Expected either ConstKind::Param or ConstKind::Unevaluated"),
}
}
- mir::ConstantKind::Val(_, _) => *self.const_to_pat(value, id, span, false).kind,
+ mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind,
}
}
fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
let (lit, neg) = match expr.kind {
hir::ExprKind::Path(ref qpath) => {
- return *self.lower_path(qpath, expr.hir_id, expr.span).kind;
+ return self.lower_path(qpath, expr.hir_id, expr.span).kind;
}
hir::ExprKind::ConstBlock(ref anon_const) => {
return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
let lit_input =
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
match self.tcx.at(expr.span).lit_to_mir_constant(lit_input) {
- Ok(constant) => *self.const_to_pat(constant, expr.hir_id, lit.span, false).kind,
+ Ok(constant) => self.const_to_pat(constant, expr.hir_id, lit.span, false).kind,
Err(LitToConstError::Reported) => PatKind::Wild,
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
}
}
}
+impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Box<[T]> {
+ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
+ self.iter().map(|t| t.fold_with(folder)).collect()
+ }
+}
+
impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option<T> {
fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
self.as_ref().map(|t| t.fold_with(folder))
PatKind::Deref { subpattern: subpattern.fold_with(folder) }
}
PatKind::Constant { value } => PatKind::Constant { value },
- PatKind::Range(range) => PatKind::Range(range),
+ PatKind::Range(ref range) => PatKind::Range(range.clone()),
PatKind::Slice { ref prefix, ref slice, ref suffix } => PatKind::Slice {
prefix: prefix.fold_with(folder),
slice: slice.fold_with(folder),
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(yeet_expr)]
+#![feature(if_let_guard)]
#![recursion_limit = "256"]
#[macro_use]
use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::Visitor as _;
use rustc_middle::mir::{
- traversal, AnalysisPhase, Body, ConstQualifs, MirPass, MirPhase, Promoted, RuntimePhase,
+ traversal, AnalysisPhase, Body, ConstQualifs, Constant, LocalDecl, MirPass, MirPhase, Operand,
+ Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, Statement, StatementKind,
+ TerminatorKind,
};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
+use rustc_span::sym;
#[macro_use]
mod pass_manager;
};
}
+fn remap_mir_for_const_eval_select<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ mut body: Body<'tcx>,
+ context: hir::Constness,
+) -> Body<'tcx> {
+ for bb in body.basic_blocks.as_mut().iter_mut() {
+ let terminator = bb.terminator.as_mut().expect("invalid terminator");
+ match terminator.kind {
+ TerminatorKind::Call {
+ func: Operand::Constant(box Constant { ref literal, .. }),
+ ref mut args,
+ destination,
+ target,
+ cleanup,
+ fn_span,
+ ..
+ } if let ty::FnDef(def_id, _) = *literal.ty().kind()
+ && tcx.item_name(def_id) == sym::const_eval_select
+ && tcx.is_intrinsic(def_id) =>
+ {
+ let [tupled_args, called_in_const, called_at_rt]: [_; 3] = std::mem::take(args).try_into().unwrap();
+ let ty = tupled_args.ty(&body.local_decls, tcx);
+ let fields = ty.tuple_fields();
+ let num_args = fields.len();
+ let func = if context == hir::Constness::Const { called_in_const } else { called_at_rt };
+ let (method, place): (fn(Place<'tcx>) -> Operand<'tcx>, Place<'tcx>) = match tupled_args {
+ Operand::Constant(_) => {
+ // there is no good way of extracting a tuple arg from a constant (const generic stuff)
+ // so we just create a temporary and deconstruct that.
+ let local = body.local_decls.push(LocalDecl::new(ty, fn_span));
+ bb.statements.push(Statement {
+ source_info: SourceInfo::outermost(fn_span),
+ kind: StatementKind::Assign(Box::new((local.into(), Rvalue::Use(tupled_args.clone())))),
+ });
+ (Operand::Move, local.into())
+ }
+ Operand::Move(place) => (Operand::Move, place),
+ Operand::Copy(place) => (Operand::Copy, place),
+ };
+ let place_elems = place.projection;
+ let arguments = (0..num_args).map(|x| {
+ let mut place_elems = place_elems.to_vec();
+ place_elems.push(ProjectionElem::Field(x.into(), fields[x]));
+ let projection = tcx.intern_place_elems(&place_elems);
+ let place = Place {
+ local: place.local,
+ projection,
+ };
+ method(place)
+ }).collect();
+ terminator.kind = TerminatorKind::Call { func, args: arguments, destination, target, cleanup, from_hir_call: false, fn_span };
+ }
+ _ => {}
+ }
+ }
+ body
+}
+
fn is_mir_available(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let def_id = def_id.expect_local();
tcx.mir_keys(()).contains(&def_id)
.body_const_context(def.did)
.expect("mir_for_ctfe should not be used for runtime functions");
- let mut body = tcx.mir_drops_elaborated_and_const_checked(def).borrow().clone();
+ let body = tcx.mir_drops_elaborated_and_const_checked(def).borrow().clone();
+
+ let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::Const);
match context {
// Do not const prop functions, either they get executed at runtime or exported to metadata,
Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other),
}
debug!("about to call mir_drops_elaborated...");
- let mut body =
+ let body =
tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
+ let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::NotConst);
debug!("body: {:#?}", body);
run_optimization_passes(tcx, &mut body);
//! method in operand position, we treat it as a neighbor of the current
//! mono item. Calls are just a special case of that.
//!
-//! #### Closures
-//! In a way, closures are a simple case. Since every closure object needs to be
-//! constructed somewhere, we can reliably discover them by observing
-//! `RValue::Aggregate` expressions with `AggregateKind::Closure`. This is also
-//! true for closures inlined from other crates.
-//!
//! #### Drop glue
//! Drop glue mono items are introduced by MIR drop-statements. The
//! generated mono item will again have drop-glue item neighbors if the
mir::TerminatorKind::Call { ref func, .. } => {
let callee_ty = func.ty(self.body, tcx);
let callee_ty = self.monomorphize(callee_ty);
- visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output);
+ visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output)
}
mir::TerminatorKind::Drop { ref place, .. }
| mir::TerminatorKind::DropAndReplace { ref place, .. } => {
/// the return type of `main`. This is not needed when
/// the user writes their own `start` manually.
fn push_extra_entry_roots(&mut self) {
- let Some((main_def_id, EntryFnType::Main)) = self.entry_fn else {
+ let Some((main_def_id, EntryFnType::Main { .. })) = self.entry_fn else {
return;
};
// Prepend `self.attrs` to `attrs`.
// FIXME: require passing an NT to prevent misuse of this method
pub(crate) fn prepend_to_nt_inner(self, attrs: &mut AttrVec) {
- let mut self_attrs = self.attrs.clone();
+ let mut self_attrs = self.attrs;
std::mem::swap(attrs, &mut self_attrs);
attrs.extend(self_attrs);
}
sym::no_implicit_prelude => {
self.check_generic_attr(hir_id, attr, target, &[Target::Mod])
}
- sym::rustc_object_lifetime_default => {
- self.check_object_lifetime_default(hir_id, span)
- }
+ sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id),
_ => {}
}
}
/// Debugging aid for `object_lifetime_default` query.
- fn check_object_lifetime_default(&self, hir_id: HirId, span: Span) {
+ fn check_object_lifetime_default(&self, hir_id: HirId) {
let tcx = self.tcx;
if let Some(generics) = tcx.hir().get_generics(tcx.hir().local_def_id(hir_id)) {
- let object_lifetime_default_reprs: String = generics
- .params
- .iter()
- .filter_map(|p| {
- let param_id = tcx.hir().local_def_id(p.hir_id);
- let default = tcx.object_lifetime_default(param_id)?;
- Some(match default {
- ObjectLifetimeDefault::Empty => "BaseDefault".to_owned(),
- ObjectLifetimeDefault::Static => "'static".to_owned(),
- ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
- ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
- })
- })
- .collect::<Vec<String>>()
- .join(",");
-
- tcx.sess.span_err(span, &object_lifetime_default_reprs);
+ for p in generics.params {
+ let hir::GenericParamKind::Type { .. } = p.kind else { continue };
+ let param_id = tcx.hir().local_def_id(p.hir_id);
+ let default = tcx.object_lifetime_default(param_id);
+ let repr = match default {
+ ObjectLifetimeDefault::Empty => "BaseDefault".to_owned(),
+ ObjectLifetimeDefault::Static => "'static".to_owned(),
+ ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
+ ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
+ };
+ tcx.sess.span_err(p.span, &repr);
+ }
}
}
sym::automatically_derived,
sym::start,
sym::rustc_main,
+ sym::unix_sigpipe,
sym::derive,
sym::test,
sym::test_case,
-use rustc_ast::{entry::EntryPointType, Attribute};
+use rustc_ast::entry::EntryPointType;
use rustc_errors::struct_span_err;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{DefIdTree, TyCtxt};
-use rustc_session::config::{CrateType, EntryFnType};
+use rustc_session::config::{sigpipe, CrateType, EntryFnType};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol, DUMMY_SP};
}
}
-fn err_if_attr_found(ctxt: &EntryContext<'_>, attrs: &[Attribute], sym: Symbol) {
+fn err_if_attr_found(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol, details: &str) {
+ let attrs = ctxt.tcx.hir().attrs(id.hir_id());
if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym) {
ctxt.tcx
.sess
- .struct_span_err(
- attr.span,
- &format!("`{}` attribute can only be used on functions", sym),
- )
+ .struct_span_err(attr.span, &format!("`{}` attribute {}", sym, details))
.emit();
}
}
let at_root = ctxt.tcx.opt_local_parent(id.def_id) == Some(CRATE_DEF_ID);
match entry_point_type(ctxt, id, at_root) {
- EntryPointType::None => (),
+ EntryPointType::None => {
+ err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`");
+ }
_ if !matches!(ctxt.tcx.def_kind(id.def_id), DefKind::Fn) => {
- let attrs = ctxt.tcx.hir().attrs(id.hir_id());
- err_if_attr_found(ctxt, attrs, sym::start);
- err_if_attr_found(ctxt, attrs, sym::rustc_main);
+ err_if_attr_found(ctxt, id, sym::start, "can only be used on functions");
+ err_if_attr_found(ctxt, id, sym::rustc_main, "can only be used on functions");
}
EntryPointType::MainNamed => (),
EntryPointType::OtherMain => {
+ err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on root `fn main()`");
ctxt.non_main_fns.push(ctxt.tcx.def_span(id.def_id));
}
EntryPointType::RustcMainAttr => {
}
}
EntryPointType::Start => {
+ err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`");
if ctxt.start_fn.is_none() {
ctxt.start_fn = Some((id.def_id, ctxt.tcx.def_span(id.def_id.to_def_id())));
} else {
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 {
- Some((def_id.to_def_id(), EntryFnType::Main))
+ } else if let Some((local_def_id, _)) = visitor.attr_main_fn {
+ let def_id = local_def_id.to_def_id();
+ Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) }))
} else {
if let Some(main_def) = tcx.resolutions(()).main_def && let Some(def_id) = main_def.opt_fn_def_id() {
// non-local main imports are handled below
)
.emit();
}
- return Some((def_id, EntryFnType::Main));
+ return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) }));
}
no_main_err(tcx, visitor);
None
}
}
+fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 {
+ if let Some(attr) = tcx.get_attr(def_id, sym::unix_sigpipe) {
+ match (attr.value_str(), attr.meta_item_list()) {
+ (Some(sym::inherit), None) => sigpipe::INHERIT,
+ (Some(sym::sig_ign), None) => sigpipe::SIG_IGN,
+ (Some(sym::sig_dfl), None) => sigpipe::SIG_DFL,
+ (_, Some(_)) => {
+ // Keep going so that `fn emit_malformed_attribute()` can print
+ // an excellent error message
+ sigpipe::DEFAULT
+ }
+ _ => {
+ tcx.sess
+ .struct_span_err(
+ attr.span,
+ "valid values for `#[unix_sigpipe = \"...\"]` are `inherit`, `sig_ign`, or `sig_dfl`",
+ )
+ .emit();
+ sigpipe::DEFAULT
+ }
+ }
+ } else {
+ sigpipe::DEFAULT
+ }
+}
+
fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
let sp = tcx.def_span(CRATE_DEF_ID);
if *tcx.sess.parse_sess.reached_eof.borrow() {
};
tcx.hir().walk_toplevel_module(&mut collector);
tcx.hir().walk_attributes(&mut collector);
- collector.print("HIR STATS");
+ collector.print("HIR STATS", "hir-stats");
}
-pub fn print_ast_stats(krate: &ast::Crate, title: &str) {
+pub fn print_ast_stats(krate: &ast::Crate, title: &str, prefix: &str) {
use rustc_ast::visit::Visitor;
let mut collector =
StatCollector { krate: None, nodes: FxHashMap::default(), seen: FxHashSet::default() };
collector.visit_crate(krate);
- collector.print(title);
+ collector.print(title, prefix);
}
impl<'k> StatCollector<'k> {
}
}
- fn print(&self, title: &str) {
+ fn print(&self, title: &str, prefix: &str) {
let mut nodes: Vec<_> = self.nodes.iter().collect();
nodes.sort_by_key(|&(_, ref node)| node.stats.count * node.stats.size);
let total_size = nodes.iter().map(|(_, node)| node.stats.count * node.stats.size).sum();
- eprintln!("\n{}\n", title);
-
- eprintln!("{:<18}{:>18}{:>14}{:>14}", "Name", "Accumulated Size", "Count", "Item Size");
- eprintln!("----------------------------------------------------------------");
+ eprintln!("{} {}", prefix, title);
+ eprintln!(
+ "{} {:<18}{:>18}{:>14}{:>14}",
+ prefix, "Name", "Accumulated Size", "Count", "Item Size"
+ );
+ eprintln!("{} ----------------------------------------------------------------", prefix);
let percent = |m, n| (m * 100) as f64 / n as f64;
for (label, node) in nodes {
let size = node.stats.count * node.stats.size;
eprintln!(
- "{:<18}{:>10} ({:4.1}%){:>14}{:>14}",
+ "{} {:<18}{:>10} ({:4.1}%){:>14}{:>14}",
+ prefix,
label,
to_readable_str(size),
percent(size, total_size),
for (label, subnode) in subnodes {
let size = subnode.count * subnode.size;
eprintln!(
- "- {:<18}{:>10} ({:4.1}%){:>14}",
+ "{} - {:<18}{:>10} ({:4.1}%){:>14}",
+ prefix,
label,
to_readable_str(size),
percent(size, total_size),
}
}
}
- eprintln!("----------------------------------------------------------------");
- eprintln!("{:<18}{:>10}\n", "Total", to_readable_str(total_size));
+ eprintln!("{} ----------------------------------------------------------------", prefix);
+ eprintln!("{} {:<18}{:>10}", prefix, "Total", to_readable_str(total_size));
+ eprintln!("{}", prefix);
}
}
+// Used to avoid boilerplate for types with many variants.
+macro_rules! record_variants {
+ (
+ ($self:ident, $val:expr, $kind:expr, $id:expr, $mod:ident, $ty:ty, $tykind:ident),
+ [$($variant:ident),*]
+ ) => {
+ match $kind {
+ $(
+ $mod::$tykind::$variant { .. } => {
+ $self.record_variant(stringify!($ty), stringify!($variant), $id, $val)
+ }
+ )*
+ }
+ };
+}
+
impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
fn visit_param(&mut self, param: &'v hir::Param<'v>) {
self.record("Param", Id::Node(param.hir_id), param);
}
fn visit_item(&mut self, i: &'v hir::Item<'v>) {
- self.record("Item", Id::Node(i.hir_id()), i);
+ record_variants!(
+ (self, i, i.kind, Id::Node(i.hir_id()), hir, Item, ItemKind),
+ [
+ ExternCrate,
+ Use,
+ Static,
+ Const,
+ Fn,
+ Macro,
+ Mod,
+ ForeignMod,
+ GlobalAsm,
+ TyAlias,
+ OpaqueTy,
+ Enum,
+ Struct,
+ Union,
+ Trait,
+ TraitAlias,
+ Impl
+ ]
+ );
hir_visit::walk_item(self, i)
}
+ fn visit_body(&mut self, b: &'v hir::Body<'v>) {
+ self.record("Body", Id::None, b);
+ hir_visit::walk_body(self, b);
+ }
+
+ fn visit_mod(&mut self, m: &'v hir::Mod<'v>, _s: Span, n: HirId) {
+ self.record("Mod", Id::None, m);
+ hir_visit::walk_mod(self, m, n)
+ }
+
fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem<'v>) {
- self.record("ForeignItem", Id::Node(i.hir_id()), i);
+ record_variants!(
+ (self, i, i.kind, Id::Node(i.hir_id()), hir, ForeignItem, ForeignItemKind),
+ [Fn, Static, Type]
+ );
hir_visit::walk_foreign_item(self, i)
}
}
fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
- self.record("Stmt", Id::Node(s.hir_id), s);
+ record_variants!(
+ (self, s, s.kind, Id::Node(s.hir_id), hir, Stmt, StmtKind),
+ [Local, Item, Expr, Semi]
+ );
hir_visit::walk_stmt(self, s)
}
}
fn visit_pat(&mut self, p: &'v hir::Pat<'v>) {
- self.record("Pat", Id::Node(p.hir_id), p);
+ record_variants!(
+ (self, p, p.kind, Id::Node(p.hir_id), hir, Pat, PatKind),
+ [Wild, Binding, Struct, TupleStruct, Or, Path, Tuple, Box, Ref, Lit, Range, Slice]
+ );
hir_visit::walk_pat(self, p)
}
- fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
- self.record("Expr", Id::Node(ex.hir_id), ex);
- hir_visit::walk_expr(self, ex)
+ fn visit_pat_field(&mut self, f: &'v hir::PatField<'v>) {
+ self.record("PatField", Id::Node(f.hir_id), f);
+ hir_visit::walk_pat_field(self, f)
+ }
+
+ fn visit_expr(&mut self, e: &'v hir::Expr<'v>) {
+ record_variants!(
+ (self, e, e.kind, Id::Node(e.hir_id), hir, Expr, ExprKind),
+ [
+ Box, ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type,
+ DropTemps, Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index,
+ Path, AddrOf, Break, Continue, Ret, InlineAsm, Struct, Repeat, Yield, Err
+ ]
+ );
+ hir_visit::walk_expr(self, e)
+ }
+
+ fn visit_let_expr(&mut self, lex: &'v hir::Let<'v>) {
+ self.record("Let", Id::Node(lex.hir_id), lex);
+ hir_visit::walk_let_expr(self, lex)
+ }
+
+ fn visit_expr_field(&mut self, f: &'v hir::ExprField<'v>) {
+ self.record("ExprField", Id::Node(f.hir_id), f);
+ hir_visit::walk_expr_field(self, f)
}
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
- self.record("Ty", Id::Node(t.hir_id), t);
+ record_variants!(
+ (self, t, t.kind, Id::Node(t.hir_id), hir, Ty, TyKind),
+ [
+ Slice,
+ Array,
+ Ptr,
+ Rptr,
+ BareFn,
+ Never,
+ Tup,
+ Path,
+ OpaqueDef,
+ TraitObject,
+ Typeof,
+ Infer,
+ Err
+ ]
+ );
hir_visit::walk_ty(self, t)
}
+ fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
+ self.record("GenericParam", Id::Node(p.hir_id), p);
+ hir_visit::walk_generic_param(self, p)
+ }
+
+ fn visit_generics(&mut self, g: &'v hir::Generics<'v>) {
+ self.record("Generics", Id::None, g);
+ hir_visit::walk_generics(self, g)
+ }
+
+ fn visit_where_predicate(&mut self, p: &'v hir::WherePredicate<'v>) {
+ record_variants!(
+ (self, p, p, Id::None, hir, WherePredicate, WherePredicate),
+ [BoundPredicate, RegionPredicate, EqPredicate]
+ );
+ hir_visit::walk_where_predicate(self, p)
+ }
+
fn visit_fn(
&mut self,
fk: hir_visit::FnKind<'v>,
hir_visit::walk_fn(self, fk, fd, b, s, id)
}
- fn visit_where_predicate(&mut self, predicate: &'v hir::WherePredicate<'v>) {
- self.record("WherePredicate", Id::None, predicate);
- hir_visit::walk_where_predicate(self, predicate)
+ fn visit_use(&mut self, p: &'v hir::Path<'v>, hir_id: hir::HirId) {
+ // This is `visit_use`, but the type is `Path` so record it that way.
+ self.record("Path", Id::None, p);
+ hir_visit::walk_use(self, p, hir_id)
}
fn visit_trait_item(&mut self, ti: &'v hir::TraitItem<'v>) {
- self.record("TraitItem", Id::Node(ti.hir_id()), ti);
+ record_variants!(
+ (self, ti, ti.kind, Id::Node(ti.hir_id()), hir, TraitItem, TraitItemKind),
+ [Const, Fn, Type]
+ );
hir_visit::walk_trait_item(self, ti)
}
+ fn visit_trait_item_ref(&mut self, ti: &'v hir::TraitItemRef) {
+ self.record("TraitItemRef", Id::Node(ti.id.hir_id()), ti);
+ hir_visit::walk_trait_item_ref(self, ti)
+ }
+
fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
- self.record("ImplItem", Id::Node(ii.hir_id()), ii);
+ record_variants!(
+ (self, ii, ii.kind, Id::Node(ii.hir_id()), hir, ImplItem, ImplItemKind),
+ [Const, Fn, TyAlias]
+ );
hir_visit::walk_impl_item(self, ii)
}
- fn visit_param_bound(&mut self, bounds: &'v hir::GenericBound<'v>) {
- self.record("GenericBound", Id::None, bounds);
- hir_visit::walk_param_bound(self, bounds)
+ fn visit_foreign_item_ref(&mut self, fi: &'v hir::ForeignItemRef) {
+ self.record("ForeignItemRef", Id::Node(fi.id.hir_id()), fi);
+ hir_visit::walk_foreign_item_ref(self, fi)
+ }
+
+ fn visit_impl_item_ref(&mut self, ii: &'v hir::ImplItemRef) {
+ self.record("ImplItemRef", Id::Node(ii.id.hir_id()), ii);
+ hir_visit::walk_impl_item_ref(self, ii)
+ }
+
+ fn visit_param_bound(&mut self, b: &'v hir::GenericBound<'v>) {
+ record_variants!(
+ (self, b, b, Id::None, hir, GenericBound, GenericBound),
+ [Trait, LangItemTrait, Outlives]
+ );
+ hir_visit::walk_param_bound(self, b)
}
fn visit_field_def(&mut self, s: &'v hir::FieldDef<'v>) {
hir_visit::walk_variant(self, v)
}
- fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
- self.record("Lifetime", Id::Node(lifetime.hir_id), lifetime);
- hir_visit::walk_lifetime(self, lifetime)
- }
-
- fn visit_qpath(&mut self, qpath: &'v hir::QPath<'v>, id: hir::HirId, span: Span) {
- self.record("QPath", Id::None, qpath);
- hir_visit::walk_qpath(self, qpath, id, span)
+ fn visit_generic_arg(&mut self, ga: &'v hir::GenericArg<'v>) {
+ record_variants!(
+ (self, ga, ga, Id::Node(ga.hir_id()), hir, GenericArg, GenericArg),
+ [Lifetime, Type, Const, Infer]
+ );
+ match ga {
+ hir::GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
+ hir::GenericArg::Type(ty) => self.visit_ty(ty),
+ hir::GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
+ hir::GenericArg::Infer(inf) => self.visit_infer(inf),
+ }
}
fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) {
hir_visit::walk_path(self, path)
}
- // `PathSegment` has one inline use (in `ast::ExprKind::MethodCall`) and
- // one non-inline use (in `Path::segments`). The latter case is more common
- // than the former case, so we implement this visitor and tolerate the
- // double counting in the former case.
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v hir::PathSegment<'v>) {
self.record("PathSegment", Id::None, path_segment);
hir_visit::walk_path_segment(self, path_span, path_segment)
}
+ fn visit_generic_args(&mut self, sp: Span, ga: &'v hir::GenericArgs<'v>) {
+ self.record("GenericArgs", Id::None, ga);
+ hir_visit::walk_generic_args(self, sp, ga)
+ }
+
fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding<'v>) {
self.record("TypeBinding", Id::Node(type_binding.hir_id), type_binding);
hir_visit::walk_assoc_type_binding(self, type_binding)
fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
self.record("Attribute", Id::Attr(attr.id), attr);
}
-}
-// Used to avoid boilerplate for types with many variants.
-macro_rules! record_variants {
- (
- ($self:ident, $val:expr, $kind:expr, $ty:ty, $tykind:ident), // mandatory pieces
- [$($variant:ident),*]
- ) => {
- match $kind {
- $(
- ast::$tykind::$variant { .. } => {
- $self.record_variant(stringify!($ty), stringify!($variant), Id::None, $val)
- }
- )*
- }
- };
+ fn visit_inline_asm(&mut self, asm: &'v hir::InlineAsm<'v>, id: HirId) {
+ self.record("InlineAsm", Id::None, asm);
+ hir_visit::walk_inline_asm(self, asm, id);
+ }
}
impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) {
record_variants!(
- (self, i, i.kind, ForeignItem, ForeignItemKind),
+ (self, i, i.kind, Id::None, ast, ForeignItem, ForeignItemKind),
[Static, Fn, TyAlias, MacCall]
);
ast_visit::walk_foreign_item(self, i)
fn visit_item(&mut self, i: &'v ast::Item) {
record_variants!(
- (self, i, i.kind, Item, ItemKind),
+ (self, i, i.kind, Id::None, ast, Item, ItemKind),
[
ExternCrate,
Use,
fn visit_stmt(&mut self, s: &'v ast::Stmt) {
record_variants!(
- (self, s, s.kind, Stmt, StmtKind),
+ (self, s, s.kind, Id::None, ast, Stmt, StmtKind),
[Local, Item, Expr, Semi, Empty, MacCall]
);
ast_visit::walk_stmt(self, s)
fn visit_pat(&mut self, p: &'v ast::Pat) {
record_variants!(
- (self, p, p.kind, Pat, PatKind),
+ (self, p, p.kind, Id::None, ast, Pat, PatKind),
[
Wild,
Ident,
fn visit_expr(&mut self, e: &'v ast::Expr) {
record_variants!(
- (self, e, e.kind, Expr, ExprKind),
+ (self, e, e.kind, Id::None, ast, Expr, ExprKind),
[
Box, Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign,
fn visit_ty(&mut self, t: &'v ast::Ty) {
record_variants!(
- (self, t, t.kind, Ty, TyKind),
+ (self, t, t.kind, Id::None, ast, Ty, TyKind),
[
Slice,
Array,
fn visit_where_predicate(&mut self, p: &'v ast::WherePredicate) {
record_variants!(
- (self, p, p, WherePredicate, WherePredicate),
+ (self, p, p, Id::None, ast, WherePredicate, WherePredicate),
[BoundPredicate, RegionPredicate, EqPredicate]
);
ast_visit::walk_where_predicate(self, p)
fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
record_variants!(
- (self, i, i.kind, AssocItem, AssocItemKind),
+ (self, i, i.kind, Id::None, ast, AssocItem, AssocItemKind),
[Const, Fn, TyAlias, MacCall]
);
ast_visit::walk_assoc_item(self, i, ctxt);
}
fn visit_param_bound(&mut self, b: &'v ast::GenericBound, _ctxt: BoundKind) {
- record_variants!((self, b, b, GenericBound, GenericBound), [Trait, Outlives]);
+ record_variants!(
+ (self, b, b, Id::None, ast, GenericBound, GenericBound),
+ [Trait, Outlives]
+ );
ast_visit::walk_param_bound(self, b)
}
// common, so we don't implement `visit_use_tree` and tolerate the missed
// coverage in the latter case.
+ // `PathSegment` has one inline use (in `ast::ExprKind::MethodCall`) and
+ // one non-inline use (in `ast::Path::segments`). The latter case is more
+ // common than the former case, so we implement this visitor and tolerate
+ // the double counting in the former case.
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v ast::PathSegment) {
self.record("PathSegment", Id::None, path_segment);
ast_visit::walk_path_segment(self, path_span, path_segment)
// common, so we implement `visit_generic_args` and tolerate the double
// counting in the former case.
fn visit_generic_args(&mut self, sp: Span, g: &'v ast::GenericArgs) {
- record_variants!((self, g, g, GenericArgs, GenericArgs), [AngleBracketed, Parenthesized]);
+ record_variants!(
+ (self, g, g, Id::None, ast, GenericArgs, GenericArgs),
+ [AngleBracketed, Parenthesized]
+ );
ast_visit::walk_generic_args(self, sp, g)
}
fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
- record_variants!((self, attr, attr.kind, Attribute, AttrKind), [Normal, DocComment]);
+ record_variants!(
+ (self, attr, attr.kind, Id::None, ast, Attribute, AttrKind),
+ [Normal, DocComment]
+ );
ast_visit::walk_attribute(self, attr)
}
//! collect them instead.
use rustc_ast::{Attribute, MetaItemKind};
+use rustc_attr::VERSION_PLACEHOLDER;
use rustc_errors::struct_span_err;
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
}
}
}
- const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER {
let version = option_env!("CFG_VERSION").unwrap_or("<current>");
self.propagate_through_expr(&f, succ)
}
- hir::ExprKind::MethodCall(.., ref args, _) => {
+ hir::ExprKind::MethodCall(.., receiver, ref args, _) => {
let succ = self.check_is_ty_uninhabited(expr, succ);
- self.propagate_through_exprs(args, succ)
+ let succ = self.propagate_through_exprs(args, succ);
+ self.propagate_through_expr(receiver, succ)
}
hir::ExprKind::Tup(ref exprs) => self.propagate_through_exprs(exprs, succ),
// added, such as `core::intrinsics::transmute`
let parents = path.segments.iter().rev().skip(1);
for path_segment in parents {
- if let Some(def_id) = path_segment.res.as_ref().and_then(Res::opt_def_id) {
+ if let Some(def_id) = path_segment.res.opt_def_id() {
// use `None` for id to prevent deprecation check
self.tcx.check_stability_allow_unstable(
def_id,
// If only some candidates are accessible, take just them
if !candidates.iter().all(|v: &ImportSuggestion| !v.accessible) {
- candidates = candidates.into_iter().filter(|x| x.accessible).collect();
+ candidates.retain(|x| x.accessible)
}
candidates
}
}
-fn object_lifetime_default<'tcx>(
- tcx: TyCtxt<'tcx>,
- param_def_id: DefId,
-) -> Option<ObjectLifetimeDefault> {
+fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> ObjectLifetimeDefault {
+ debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
let param_def_id = param_def_id.expect_local();
let parent_def_id = tcx.local_parent(param_def_id);
- let generics = tcx.hir().get_generics(parent_def_id)?;
+ let generics = tcx.hir().get_generics(parent_def_id).unwrap();
let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
- let param = generics.params.iter().find(|p| p.hir_id == param_hir_id)?;
+ let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
// Scan the bounds and where-clauses on parameters to extract bounds
// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
// for each type parameter.
match param.kind {
- GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { .. } => {
let mut set = Set1::Empty;
}
}
- Some(match set {
+ match set {
Set1::Empty => ObjectLifetimeDefault::Empty,
Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
Set1::One(hir::LifetimeName::Param(param_def_id, _)) => {
ObjectLifetimeDefault::Param(param_def_id.to_def_id())
}
_ => ObjectLifetimeDefault::Ambiguous,
- })
+ }
}
- GenericParamKind::Const { .. } => {
- // Generic consts don't impose any constraints.
- //
- // We still store a dummy value here to allow generic parameters
- // in an arbitrary order.
- Some(ObjectLifetimeDefault::Empty)
+ _ => {
+ bug!("object_lifetime_default_raw must only be called on a type parameter")
}
}
}
generics
.params
.iter()
- .filter_map(|param| self.tcx.object_lifetime_default(param.def_id))
+ .filter_map(|param| {
+ match self.tcx.def_kind(param.def_id) {
+ // Generic consts don't impose any constraints.
+ //
+ // We still store a dummy value here to allow generic parameters
+ // in an arbitrary order.
+ DefKind::ConstParam => Some(ObjectLifetimeDefault::Empty),
+ DefKind::TyParam => Some(self.tcx.object_lifetime_default(param.def_id)),
+ // We may also get a `Trait` or `TraitAlias` because of how generics `Self` parameter
+ // works. Ignore it because it can't have a meaningful lifetime default.
+ DefKind::LifetimeParam | DefKind::Trait | DefKind::TraitAlias => None,
+ dk => bug!("unexpected def_kind {:?}", dk),
+ }
+ })
.map(set_to_region)
.collect()
});
label_res_map: NodeMap<NodeId>,
/// Resolutions for lifetimes.
lifetimes_res_map: NodeMap<LifetimeRes>,
- /// Mapping from generics `def_id`s to TAIT generics `def_id`s.
- /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
- /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
- /// field from the original parameter 'a to the new parameter 'a1.
- generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
/// Lifetime parameters that lowering will have to introduce.
extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, LifetimeRes)>>,
import_res_map: Default::default(),
label_res_map: Default::default(),
lifetimes_res_map: Default::default(),
- generics_def_id_map: Vec::new(),
extra_lifetime_params_map: Default::default(),
extern_crate_map: Default::default(),
reexport_map: FxHashMap::default(),
import_res_map: self.import_res_map,
label_res_map: self.label_res_map,
lifetimes_res_map: self.lifetimes_res_map,
- generics_def_id_map: self.generics_def_id_map,
extra_lifetime_params_map: self.extra_lifetime_params_map,
next_node_id: self.next_node_id,
node_id_to_def_id: self.node_id_to_def_id,
import_res_map: self.import_res_map.clone(),
label_res_map: self.label_res_map.clone(),
lifetimes_res_map: self.lifetimes_res_map.clone(),
- generics_def_id_map: self.generics_def_id_map.clone(),
extra_lifetime_params_map: self.extra_lifetime_params_map.clone(),
next_node_id: self.next_node_id.clone(),
node_id_to_def_id: self.node_id_to_def_id.clone(),
&mut self,
ex: &'tcx hir::Expr<'tcx>,
seg: &'tcx hir::PathSegment<'tcx>,
+ receiver: &'tcx hir::Expr<'tcx>,
args: &'tcx [hir::Expr<'tcx>],
) {
debug!("process_method_call {:?} {:?}", ex, ex.span);
}
// walk receiver and args
+ self.visit_expr(receiver);
walk_list!(self, visit_expr, args);
}
_,
)
| Res::SelfTy { .. } => {
- self.dump_path_segment_ref(id, &hir::PathSegment::from_ident(ident));
+ self.dump_path_segment_ref(
+ id,
+ &hir::PathSegment::new(ident, hir::HirId::INVALID, Res::Err),
+ );
}
def => {
error!("unexpected definition kind when processing collected idents: {:?}", def)
self.process_macro_use(trait_item.span);
match trait_item.kind {
hir::TraitItemKind::Const(ref ty, body) => {
- let body = body.map(|b| &self.tcx.hir().body(b).value);
+ let body = body.map(|b| self.tcx.hir().body(b).value);
let attrs = self.tcx.hir().attrs(trait_item.hir_id());
self.process_assoc_const(
trait_item.def_id,
let res = self.save_ctxt.get_path_res(hir_expr.hir_id);
self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), *rest)
}
- hir::ExprKind::MethodCall(ref seg, args, _) => self.process_method_call(ex, seg, args),
+ hir::ExprKind::MethodCall(ref seg, receiver, args, _) => {
+ self.process_method_call(ex, seg, receiver, args)
+ }
hir::ExprKind::Field(ref sub_ex, _) => {
self.visit_expr(&sub_ex);
Node::TraitRef(tr) => tr.path.res,
Node::Item(&hir::Item { kind: hir::ItemKind::Use(path, _), .. }) => path.res,
- Node::PathSegment(seg) => match seg.res {
- Some(res) if res != Res::Err => res,
- _ => {
+ Node::PathSegment(seg) => {
+ if seg.res != Res::Err {
+ seg.res
+ } else {
let parent_node = self.tcx.hir().get_parent_node(hir_id);
self.get_path_res(parent_node)
}
- },
+ }
Node::Expr(&hir::Expr { kind: hir::ExprKind::Struct(ref qpath, ..), .. }) => {
self.typeck_results().qpath_res(qpath, hir_id)
}
pub fn get_path_segment_data(&self, path_seg: &hir::PathSegment<'_>) -> Option<Ref> {
- self.get_path_segment_data_with_id(path_seg, path_seg.hir_id?)
+ self.get_path_segment_data_with_id(path_seg, path_seg.hir_id)
}
pub fn get_path_segment_data_with_id(
use std::path::{Path, PathBuf};
use std::str::{self, FromStr};
+pub mod sigpipe;
+
/// The different settings that the `-C strip` flag can have.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum Strip {
// The type of entry function, so users can have their own entry functions
#[derive(Copy, Clone, PartialEq, Hash, Debug, HashStable_Generic)]
pub enum EntryFnType {
- Main,
+ Main {
+ /// Specifies what to do with `SIGPIPE` before calling `fn main()`.
+ ///
+ /// What values that are valid and what they mean must be in sync
+ /// across rustc and libstd, but we don't want it public in libstd,
+ /// so we take a bit of an unusual approach with simple constants
+ /// and an `include!()`.
+ sigpipe: u8,
+ },
Start,
}
sess.fatal(&err);
});
- let mut ret = FxHashSet::default();
+ let mut ret = CrateConfig::default();
ret.reserve(7); // the minimum number of insertions
// Target bindings.
ret.insert((sym::target_os, Some(Symbol::intern(os))));
--- /dev/null
+//! NOTE: Keep these constants in sync with `library/std/src/sys/unix/mod.rs`!
+
+/// Do not touch `SIGPIPE`. Use whatever the parent process uses.
+#[allow(dead_code)]
+pub const INHERIT: u8 = 1;
+
+/// Change `SIGPIPE` to `SIG_IGN` so that failed writes results in `EPIPE`
+/// that are eventually converted to `ErrorKind::BrokenPipe`.
+#[allow(dead_code)]
+pub const SIG_IGN: u8 = 2;
+
+/// Change `SIGPIPE` to `SIG_DFL` so that the process is killed when trying
+/// to write to a closed pipe. This is usually the desired behavior for CLI
+/// apps that produce textual output that you want to pipe to other programs
+/// such as `head -n 1`.
+#[allow(dead_code)]
+pub const SIG_DFL: u8 = 3;
+
+/// `SIG_IGN` has been the Rust default since 2014. See
+/// <https://github.com/rust-lang/rust/issues/62569>.
+#[allow(dead_code)]
+pub const DEFAULT: u8 = SIG_IGN;
};
use crate::SessionDiagnostic;
use rustc_ast::node_id::NodeId;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::sync::{Lock, Lrc};
use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
use rustc_errors::{
/// The set of keys (and, optionally, values) that define the compilation
/// environment of the crate, used to drive conditional compilation.
-pub type CrateConfig = FxHashSet<(Symbol, Option<Symbol>)>;
+pub type CrateConfig = FxIndexSet<(Symbol, Option<Symbol>)>;
pub type CrateCheckConfig = CheckCfg<Symbol>;
/// Collected spans during parsing for places where a certain feature was
Self {
span_diagnostic: handler,
unstable_features: UnstableFeatures::from_environment(None),
- config: FxHashSet::default(),
+ config: FxIndexSet::default(),
check_config: CrateCheckConfig::default(),
edition: ExpnId::root().expn_data().edition,
raw_identifier_spans: Lock::new(Vec::new()),
}
}
+impl rustc_errors::IntoDiagnosticArg for Limit {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct Limits {
/// The maximum recursion limit for potentially infinitely recursive
alias,
align,
align_offset,
+ alignment,
alignstack,
all,
alloc,
const_deallocate,
const_eval_limit,
const_eval_select,
- const_eval_select_ct,
const_evaluatable_checked,
const_extern_fn,
const_fn,
emit_struct,
emit_struct_field,
enable,
- enclosing_scope,
encode,
end,
env,
infer_outlives_requirements,
infer_static_outlives_requirements,
inherent_associated_types,
+ inherit,
inlateout,
inline,
inline_const,
lib,
libc,
lifetime,
+ lifetimes,
likely,
line,
line_macro,
panic_unwind,
panicking,
param_attrs,
+ parent_label,
partial_cmp,
partial_ord,
passes,
rustfmt,
rvalue_static_promotion,
s,
+ safety,
sanitize,
sanitizer_runtime,
saturating_add,
should_panic,
shr,
shr_assign,
+ sig_dfl,
+ sig_ign,
simd,
simd_add,
simd_and,
trait_alias,
trait_upcasting,
transmute,
+ transmute_opts,
transmute_trait,
transparent,
transparent_enums,
unit,
universal_impl_trait,
unix,
+ unix_sigpipe,
unlikely,
unmarked_api,
unpin,
va_list,
va_start,
val,
+ validity,
values,
var,
variant_count,
+use crate::errors::AutoDerefReachedRecursionLimit;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::{self, TraitEngine};
-use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_infer::infer::InferCtxt;
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt};
Limit(0) => Limit(2),
limit => limit * 2,
};
- struct_span_err!(
- tcx.sess,
+ tcx.sess.emit_err(AutoDerefReachedRecursionLimit {
span,
- E0055,
- "reached the recursion limit while auto-dereferencing `{:?}`",
- ty
- )
- .span_label(span, "deref recursion limit reached")
- .help(&format!(
- "consider increasing the recursion limit by adding a \
- `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
+ ty,
suggested_limit,
- tcx.crate_name(LOCAL_CRATE),
- ))
- .emit();
+ crate_name: tcx.crate_name(LOCAL_CRATE),
+ });
}
--- /dev/null
+use rustc_errors::{fluent, ErrorGuaranteed};
+use rustc_macros::SessionDiagnostic;
+use rustc_middle::ty::{PolyTraitRef, Ty, Unevaluated};
+use rustc_session::{parse::ParseSess, Limit, SessionDiagnostic};
+use rustc_span::{Span, Symbol};
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::dump_vtable_entries)]
+pub struct DumpVTableEntries<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub trait_ref: PolyTraitRef<'a>,
+ pub entries: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::unable_to_construct_constant_value)]
+pub struct UnableToConstructConstantValue<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub unevaluated: Unevaluated<'a>,
+}
+
+#[derive(SessionDiagnostic)]
+#[help]
+#[diag(trait_selection::auto_deref_reached_recursion_limit, code = "E0055")]
+pub struct AutoDerefReachedRecursionLimit<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub ty: Ty<'a>,
+ pub suggested_limit: Limit,
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+pub struct EmptyOnClauseInOnUnimplemented {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+pub struct InvalidOnClauseInOnUnimplemented {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::no_value_in_rustc_on_unimplemented, code = "E0232")]
+#[note]
+pub struct NoValueInOnUnimplemented {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+pub struct NegativePositiveConflict<'a> {
+ pub impl_span: Span,
+ pub trait_desc: &'a str,
+ pub self_desc: &'a Option<String>,
+ pub negative_impl_span: Result<Span, Symbol>,
+ pub positive_impl_span: Result<Span, Symbol>,
+}
+
+impl SessionDiagnostic<'_> for NegativePositiveConflict<'_> {
+ fn into_diagnostic(
+ self,
+ sess: &ParseSess,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = sess.struct_err(fluent::trait_selection::negative_positive_conflict);
+ diag.set_arg("trait_desc", self.trait_desc);
+ diag.set_arg(
+ "self_desc",
+ self.self_desc.clone().map_or_else(|| String::from("none"), |ty| ty),
+ );
+ diag.set_span(self.impl_span);
+ diag.code(rustc_errors::error_code!(E0751));
+ match self.negative_impl_span {
+ Ok(span) => {
+ diag.span_label(span, fluent::trait_selection::negative_implementation_here);
+ }
+ Err(cname) => {
+ diag.note(fluent::trait_selection::negative_implementation_in_crate);
+ diag.set_arg("negative_impl_cname", cname.to_string());
+ }
+ }
+ match self.positive_impl_span {
+ Ok(span) => {
+ diag.span_label(span, fluent::trait_selection::positive_implementation_here);
+ }
+ Err(cname) => {
+ diag.note(fluent::trait_selection::positive_implementation_in_crate);
+ diag.set_arg("positive_impl_cname", cname.to_string());
+ }
+ }
+ diag
+ }
+}
extern crate smallvec;
pub mod autoderef;
+pub mod errors;
pub mod infer;
pub mod traits;
use super::*;
+use crate::errors::UnableToConstructConstantValue;
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::InferCtxt;
use crate::traits::project::ProjectAndUnifyResult;
Ok(None) => {
let tcx = self.tcx;
let def_id = unevaluated.def.did;
- let reported = tcx.sess.struct_span_err(tcx.def_span(def_id), &format!("unable to construct a constant value for the unevaluated constant {:?}", unevaluated)).emit();
-
+ let reported =
+ tcx.sess.emit_err(UnableToConstructConstantValue {
+ span: tcx.def_span(def_id),
+ unevaluated,
+ });
Err(ErrorHandled::Reported(reported))
}
Err(err) => Err(err),
message,
label,
note,
- enclosing_scope,
+ parent_label,
append_const_msg,
} = self.on_unimplemented_note(trait_ref, &obligation);
let have_alt_message = message.is_some() || label.is_some();
{
"consider using `()`, or a `Result`".to_owned()
} else {
- format!(
- "{}the trait `{}` is not implemented for `{}`",
- pre_message,
- trait_predicate.print_modifiers_and_trait_path(),
- trait_ref.skip_binder().self_ty(),
- )
+ let ty_desc = match trait_ref.skip_binder().self_ty().kind() {
+ ty::FnDef(_, _) => Some("fn item"),
+ ty::Closure(_, _) => Some("closure"),
+ _ => None,
+ };
+
+ match ty_desc {
+ Some(desc) => format!(
+ "{}the trait `{}` is not implemented for {} `{}`",
+ pre_message,
+ trait_predicate.print_modifiers_and_trait_path(),
+ desc,
+ trait_ref.skip_binder().self_ty(),
+ ),
+ None => format!(
+ "{}the trait `{}` is not implemented for `{}`",
+ pre_message,
+ trait_predicate.print_modifiers_and_trait_path(),
+ trait_ref.skip_binder().self_ty(),
+ ),
+ }
};
if self.suggest_add_reference_to_arg(
// If it has a custom `#[rustc_on_unimplemented]` note, let's display it
err.note(s.as_str());
}
- if let Some(ref s) = enclosing_scope {
+ if let Some(ref s) = parent_label {
let body = tcx
.hir()
.opt_local_def_id(obligation.cause.body_id)
hir_id: obligation.cause.body_id,
})
});
-
- let enclosing_scope_span =
- tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(body));
-
- err.span_label(enclosing_scope_span, s);
+ err.span_label(tcx.def_span(body), s);
}
self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref);
return false;
}
if candidates.len() == 1 {
+ let ty_desc = match candidates[0].self_ty().kind() {
+ ty::FnPtr(_) => Some("fn pointer"),
+ _ => None,
+ };
+ let the_desc = match ty_desc {
+ Some(desc) => format!(" implemented for {} `", desc),
+ None => " implemented for `".to_string(),
+ };
err.highlighted_help(vec![
(
format!("the trait `{}` ", candidates[0].print_only_trait_path()),
Style::NoStyle,
),
("is".to_string(), Style::Highlight),
- (" implemented for `".to_string(), Style::NoStyle),
+ (the_desc, Style::NoStyle),
(candidates[0].self_ty().to_string(), Style::Highlight),
("`".to_string(), Style::NoStyle),
]);
&& let [
..,
trait_path_segment @ hir::PathSegment {
- res: Some(rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id)),
+ res: rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id),
..
},
hir::PathSegment {
ident: assoc_item_name,
- res: Some(rustc_hir::def::Res::Def(_, item_id)),
+ res: rustc_hir::def::Res::Def(_, item_id),
..
}
] = path.segments
mod util;
pub mod wf;
+use crate::errors::DumpVTableEntries;
use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::{InferCtxt, TyCtxtInferExt};
use crate::traits::error_reporting::InferCtxtExt as _;
trait_ref: ty::PolyTraitRef<'tcx>,
entries: &[VtblEntry<'tcx>],
) {
- let msg = format!("vtable entries for `{}`: {:#?}", trait_ref, entries);
- tcx.sess.struct_span_err(sp, &msg).emit();
+ tcx.sess.emit_err(DumpVTableEntries {
+ span: sp,
+ trait_ref,
+ entries: format!("{:#?}", entries),
+ });
}
fn own_existential_vtable_entries<'tcx>(
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
+use crate::errors::{
+ EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
+};
+
#[derive(Clone, Debug)]
pub struct OnUnimplementedFormatString(Symbol);
pub message: Option<OnUnimplementedFormatString>,
pub label: Option<OnUnimplementedFormatString>,
pub note: Option<OnUnimplementedFormatString>,
- pub enclosing_scope: Option<OnUnimplementedFormatString>,
+ pub parent_label: Option<OnUnimplementedFormatString>,
pub append_const_msg: Option<Option<Symbol>>,
}
pub message: Option<String>,
pub label: Option<String>,
pub note: Option<String>,
- pub enclosing_scope: Option<String>,
+ pub parent_label: Option<String>,
/// Append a message for `~const Trait` errors. `None` means not requested and
/// should fallback to a generic message, `Some(None)` suggests using the default
/// appended message, `Some(Some(s))` suggests use the `s` message instead of the
pub append_const_msg: Option<Option<Symbol>>,
}
-fn parse_error(
- tcx: TyCtxt<'_>,
- span: Span,
- message: &str,
- label: &str,
- note: Option<&str>,
-) -> ErrorGuaranteed {
- let mut diag = struct_span_err!(tcx.sess, span, E0232, "{}", message);
- diag.span_label(span, label);
- if let Some(note) = note {
- diag.note(note);
- }
- diag.emit()
-}
-
impl<'tcx> OnUnimplementedDirective {
fn parse(
tcx: TyCtxt<'tcx>,
} else {
let cond = item_iter
.next()
- .ok_or_else(|| {
- parse_error(
- tcx,
- span,
- "empty `on`-clause in `#[rustc_on_unimplemented]`",
- "empty on-clause here",
- None,
- )
- })?
+ .ok_or_else(|| tcx.sess.emit_err(EmptyOnClauseInOnUnimplemented { span }))?
.meta_item()
- .ok_or_else(|| {
- parse_error(
- tcx,
- span,
- "invalid `on`-clause in `#[rustc_on_unimplemented]`",
- "invalid on-clause here",
- None,
- )
- })?;
+ .ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
if let Some(value) = cfg.value && let Err(guar) = parse_value(value) {
errored = Some(guar);
let mut message = None;
let mut label = None;
let mut note = None;
- let mut enclosing_scope = None;
+ let mut parent_label = None;
let mut subcommands = vec![];
let mut append_const_msg = None;
note = parse_value(note_)?;
continue;
}
- } else if item.has_name(sym::enclosing_scope) && enclosing_scope.is_none() {
- if let Some(enclosing_scope_) = item.value_str() {
- enclosing_scope = parse_value(enclosing_scope_)?;
+ } else if item.has_name(sym::parent_label) && parent_label.is_none() {
+ if let Some(parent_label_) = item.value_str() {
+ parent_label = parse_value(parent_label_)?;
continue;
}
} else if item.has_name(sym::on)
}
// nothing found
- parse_error(
- tcx,
- item.span(),
- "this attribute must have a valid value",
- "expected value here",
- Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#),
- );
+ tcx.sess.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
if let Some(reported) = errored {
message,
label,
note,
- enclosing_scope,
+ parent_label,
append_const_msg,
})
}
attr.span,
)?),
note: None,
- enclosing_scope: None,
+ parent_label: None,
append_const_msg: None,
}))
} else {
let mut message = None;
let mut label = None;
let mut note = None;
- let mut enclosing_scope = None;
+ let mut parent_label = None;
let mut append_const_msg = None;
info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
note = Some(note_.clone());
}
- if let Some(ref enclosing_scope_) = command.enclosing_scope {
- enclosing_scope = Some(enclosing_scope_.clone());
+ if let Some(ref parent_label_) = command.parent_label {
+ parent_label = Some(parent_label_.clone());
}
append_const_msg = command.append_const_msg;
label: label.map(|l| l.format(tcx, trait_ref, &options_map)),
message: message.map(|m| m.format(tcx, trait_ref, &options_map)),
note: note.map(|n| n.format(tcx, trait_ref, &options_map)),
- enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options_map)),
+ parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, &options_map)),
append_const_msg,
}
}
let predicate = obligation.predicate;
let type_at = |i| predicate.map_bound(|p| p.trait_ref.substs.type_at(i));
- let bool_at = |i| {
- predicate
- .skip_binder()
- .trait_ref
- .substs
- .const_at(i)
- .try_eval_bool(self.tcx(), obligation.param_env)
- .unwrap_or(true)
- };
+ let const_at = |i| predicate.skip_binder().trait_ref.substs.const_at(i);
let src_and_dst = predicate.map_bound(|p| rustc_transmute::Types {
- src: p.trait_ref.substs.type_at(1),
dst: p.trait_ref.substs.type_at(0),
+ src: p.trait_ref.substs.type_at(1),
});
let scope = type_at(2).skip_binder();
- let assume = rustc_transmute::Assume {
- alignment: bool_at(3),
- lifetimes: bool_at(4),
- validity: bool_at(5),
- visibility: bool_at(6),
- };
+ let assume =
+ rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, const_at(3));
let cause = obligation.cause.clone();
pub mod specialization_graph;
use specialization_graph::GraphExt;
+use crate::errors::NegativePositiveConflict;
use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use crate::traits::select::IntercrateAmbiguityCause;
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
positive_impl_def_id: DefId,
sg: &mut specialization_graph::Graph,
) {
- let impl_span = tcx.def_span(local_impl_def_id);
-
- let mut err = struct_span_err!(
- tcx.sess,
- impl_span,
- E0751,
- "found both positive and negative implementation of trait `{}`{}:",
- overlap.trait_desc,
- overlap.self_desc.clone().map_or_else(String::new, |ty| format!(" for type `{}`", ty))
- );
-
- match tcx.span_of_impl(negative_impl_def_id) {
- Ok(span) => {
- err.span_label(span, "negative implementation here");
- }
- Err(cname) => {
- err.note(&format!("negative implementation in crate `{}`", cname));
- }
- }
-
- match tcx.span_of_impl(positive_impl_def_id) {
- Ok(span) => {
- err.span_label(span, "positive implementation here");
- }
- Err(cname) => {
- err.note(&format!("positive implementation in crate `{}`", cname));
- }
- }
-
+ let mut err = tcx.sess.create_err(NegativePositiveConflict {
+ impl_span: tcx.def_span(local_impl_def_id),
+ trait_desc: &overlap.trait_desc,
+ self_desc: &overlap.self_desc,
+ negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
+ positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
+ });
sg.has_errored = Some(err.emit());
}
[dependencies]
tracing = "0.1"
-rustc_data_structures = { path = "../rustc_data_structures", optional = true}
+rustc_data_structures = { path = "../rustc_data_structures"}
+rustc_hir = { path = "../rustc_hir", optional = true}
rustc_infer = { path = "../rustc_infer", optional = true}
rustc_macros = { path = "../rustc_macros", optional = true}
rustc_middle = { path = "../rustc_middle", optional = true}
[features]
rustc = [
"rustc_middle",
- "rustc_data_structures",
+ "rustc_hir",
"rustc_infer",
"rustc_macros",
"rustc_span",
}
#[instrument(level = "debug")]
- #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))]
pub(crate) fn from_nfa(nfa: Nfa<R>) -> Self {
let Nfa { transitions: nfa_transitions, start: nfa_start, accepting: nfa_accepting } = nfa;
let mut transitions: Map<State, Map<Transition<R>, Set<State>>> = self.transitions;
- // the iteration order doesn't matter
- #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))]
for (source, transition) in other.transitions {
let fix_state = |state| if state == other.start { self.accepting } else { state };
let entry = transitions.entry(fix_state(source)).or_default();
let mut transitions: Map<State, Map<Transition<R>, Set<State>>> = self.transitions.clone();
- // the iteration order doesn't matter
- #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))]
for (&(mut source), transition) in other.transitions.iter() {
// if source is starting state of `other`, replace with starting state of `self`
if source == other.start {
let entry = transitions.entry(source).or_default();
for (edge, destinations) in transition {
let entry = entry.entry(edge.clone()).or_default();
- // the iteration order doesn't matter
- #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))]
for &(mut destination) in destinations {
// if dest is accepting state of `other`, replace with accepting state of `self`
if destination == other.accepting {
#[macro_use]
extern crate tracing;
-#[cfg(feature = "rustc")]
-pub(crate) use rustc_data_structures::fx::{FxHashMap as Map, FxHashSet as Set};
-
-#[cfg(not(feature = "rustc"))]
-pub(crate) use std::collections::{HashMap as Map, HashSet as Set};
+pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set};
pub(crate) mod layout;
pub(crate) mod maybe_transmutable;
pub struct Assume {
pub alignment: bool,
pub lifetimes: bool,
+ pub safety: bool,
pub validity: bool,
- pub visibility: bool,
}
/// The type encodes answers to the question: "Are these types transmutable?"
#[cfg(feature = "rustc")]
mod rustc {
+ use super::*;
+
+ use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::InferCtxt;
use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::Binder;
+ use rustc_middle::ty::Const;
+ use rustc_middle::ty::ParamEnv;
use rustc_middle::ty::Ty;
+ use rustc_middle::ty::TyCtxt;
/// The source and destination types of a transmutation.
#[derive(TypeFoldable, TypeVisitable, Debug, Clone, Copy)]
.answer()
}
}
+
+ impl Assume {
+ /// Constructs an `Assume` from a given const-`Assume`.
+ pub fn from_const<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ c: Const<'tcx>,
+ ) -> Self {
+ use rustc_middle::ty::ScalarInt;
+ use rustc_middle::ty::TypeVisitable;
+ use rustc_span::symbol::sym;
+
+ let c = c.eval(tcx, param_env);
+
+ if let Some(err) = c.error_reported() {
+ return Self { alignment: true, lifetimes: true, safety: true, validity: true };
+ }
+
+ let adt_def = c.ty().ty_adt_def().expect("The given `Const` must be an ADT.");
+
+ assert_eq!(
+ tcx.require_lang_item(LangItem::TransmuteOpts, None),
+ adt_def.did(),
+ "The given `Const` was not marked with the `{}` lang item.",
+ LangItem::TransmuteOpts.name(),
+ );
+
+ let variant = adt_def.non_enum_variant();
+ let fields = c.to_valtree().unwrap_branch();
+
+ let get_field = |name| {
+ let (field_idx, _) = variant
+ .fields
+ .iter()
+ .enumerate()
+ .find(|(_, field_def)| name == field_def.name)
+ .expect(&format!("There were no fields named `{name}`."));
+ fields[field_idx].unwrap_leaf() == ScalarInt::TRUE
+ };
+
+ Self {
+ alignment: get_field(sym::alignment),
+ lifetimes: get_field(sym::lifetimes),
+ safety: get_field(sym::safety),
+ validity: get_field(sym::validity),
+ }
+ }
+ }
}
#[cfg(feature = "rustc")]
#[inline(always)]
#[instrument(level = "debug", skip(self), fields(src = ?self.src, dst = ?self.dst))]
pub(crate) fn answer(self) -> Answer<<C as QueryContext>::Ref> {
- let assume_visibility = self.assume.visibility;
+ let assume_visibility = self.assume.safety;
let query_or_answer = self.map_layouts(|src, dst, scope, context| {
// Remove all `Def` nodes from `src`, without checking their visibility.
let src = src.prune(&|def| true);
layout::Tree::<Def, !>::bool(),
layout::Tree::<Def, !>::bool(),
(),
- crate::Assume { alignment: false, lifetimes: false, validity: true, visibility: false },
+ crate::Assume { alignment: false, lifetimes: false, validity: true, safety: false },
UltraMinimal,
)
.answer();
layout::Dfa::<!>::bool(),
layout::Dfa::<!>::bool(),
(),
- crate::Assume { alignment: false, lifetimes: false, validity: true, visibility: false },
+ crate::Assume { alignment: false, lifetimes: false, validity: true, safety: false },
UltraMinimal,
)
.answer();
return true;
}
- match pat.kind.as_ref() {
+ match pat.kind {
thir::PatKind::Constant { value } => value.has_param_types_or_consts(),
- thir::PatKind::Range(thir::PatRange { lo, hi, .. }) => {
+ thir::PatKind::Range(box thir::PatRange { lo, hi, .. }) => {
lo.has_param_types_or_consts() || hi.has_param_types_or_consts()
}
_ => false,
multispan.push_span_label(span_late, note);
tcx.struct_span_lint_hir(
LATE_BOUND_LIFETIME_ARGUMENTS,
- args.args[0].id(),
+ args.args[0].hir_id(),
multispan,
|lint| {
lint.build(msg).emit();
if has_default {
tcx.check_optional_stability(
param.def_id,
- Some(arg.id()),
+ Some(arg.hir_id()),
arg.span(),
None,
AllowUnstable::No,
let ident = Ident::new(assoc_item.name, binding.item_name.span);
let item_segment = hir::PathSegment {
ident,
- hir_id: Some(binding.hir_id),
- res: None,
+ hir_id: binding.hir_id,
+ res: Res::Err,
args: Some(binding.gen_args),
infer_args: false,
};
[.., hir::PathSegment {
ident,
args,
- res: Some(Res::Def(DefKind::Enum, _)),
+ res: Res::Def(DefKind::Enum, _),
..
}, _] => (
// We need to include the `::` in `Type::Variant::<Args>`
let types_and_spans: Vec<_> = segments
.clone()
.flat_map(|segment| {
- segment.res.and_then(|res| {
- if segment.args().args.is_empty() {
- None
- } else {
- Some((
- match res {
- Res::PrimTy(ty) => format!("{} `{}`", res.descr(), ty.name()),
+ if segment.args().args.is_empty() {
+ None
+ } else {
+ Some((
+ match segment.res {
+ Res::PrimTy(ty) => format!("{} `{}`", segment.res.descr(), ty.name()),
Res::Def(_, def_id)
if let Some(name) = self.tcx().opt_item_name(def_id) => {
- format!("{} `{name}`", res.descr())
+ format!("{} `{name}`", segment.res.descr())
}
Res::Err => "this type".to_string(),
- _ => res.descr().to_string(),
+ _ => segment.res.descr().to_string(),
},
segment.ident.span,
))
- }
- })
+ }
})
.collect();
let this_type = match &types_and_spans[..] {
fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
match arg.kind {
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
- [
- PathSegment {
- res: Some(Res::SelfTy { trait_: _, alias_to: impl_ref }),
- ..
- },
- ] => {
+ [PathSegment { res: Res::SelfTy { trait_: _, alias_to: impl_ref }, .. }] => {
let impl_ty_name =
impl_ref.map(|(def_id, _)| self.tcx.def_path_str(def_id));
self.selftys.push((path.span, impl_ty_name));
self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
self.suggest_missing_parentheses(err, expr);
self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected);
+ self.suggest_copied_or_cloned(err, expr, expr_ty, expected);
self.note_type_is_not_clone(err, expected, expr_ty, expr);
self.note_need_for_fn_pointer(err, expected, expr_ty);
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
let closure_params_len = closure_fn_decl.inputs.len();
let (
Some(Node::Expr(hir::Expr {
- kind: hir::ExprKind::MethodCall(method_path, method_expr, _),
+ kind: hir::ExprKind::MethodCall(method_path, receiver, ..),
..
})),
1,
return None;
};
- let self_ty = self.typeck_results.borrow().expr_ty(&method_expr[0]);
+ let self_ty = self.typeck_results.borrow().expr_ty(receiver);
let name = method_path.ident.name;
let is_as_ref_able = match self_ty.peel_refs().kind() {
ty::Adt(def, _) => {
};
if self.can_coerce(ref_ty, expected) {
let mut sugg_sp = sp;
- if let hir::ExprKind::MethodCall(ref segment, ref args, _) = expr.kind {
+ if let hir::ExprKind::MethodCall(ref segment, receiver, args, _) = expr.kind {
let clone_trait =
self.tcx.require_lang_item(LangItem::Clone, Some(segment.ident.span));
- if let ([arg], Some(true), sym::clone) = (
- &args[..],
- self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
+ if args.is_empty()
+ && self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
|did| {
let ai = self.tcx.associated_item(did);
ai.trait_container(self.tcx) == Some(clone_trait)
},
- ),
- segment.ident.name,
- ) {
+ ) == Some(true)
+ && segment.ident.name == sym::clone
+ {
// If this expression had a clone call when suggesting borrowing
// we want to suggest removing it because it'd now be unnecessary.
- sugg_sp = arg.span;
+ sugg_sp = receiver.span;
}
}
if let Ok(src) = sm.span_to_snippet(sugg_sp) {
}
ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected),
ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected),
- ExprKind::MethodCall(segment, args, _) => {
- self.check_method_call(expr, segment, args, expected)
+ ExprKind::MethodCall(segment, receiver, args, _) => {
+ self.check_method_call(expr, segment, receiver, args, expected)
}
ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr),
ExprKind::Type(e, t) => {
// We just want to check sizedness, so instead of introducing
// placeholder lifetimes with probing, we just replace higher lifetimes
// with fresh vars.
- let arg_span = args.get(i).map(|a| a.span);
- let span = arg_span.unwrap_or(expr.span);
+ let span = args.get(i).map(|a| a.span).unwrap_or(expr.span);
let input = self.replace_bound_vars_with_fresh_vars(
span,
infer::LateBoundRegionConversionTime::FnCall,
fn_sig.input(i),
);
- self.require_type_is_sized(
- self.normalize_associated_types_in(span, input),
+ self.require_type_is_sized_deferred(
+ input,
span,
- traits::SizedArgumentType(arg_span),
+ traits::SizedArgumentType(None),
);
}
}
infer::LateBoundRegionConversionTime::FnCall,
fn_sig.output(),
);
- self.require_type_is_sized(
- self.normalize_associated_types_in(expr.span, output),
- expr.span,
- traits::SizedReturnType,
- );
+ self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType);
}
// We always require that the type provided as the value for
&self,
expr: &'tcx hir::Expr<'tcx>,
segment: &hir::PathSegment<'_>,
+ rcvr: &'tcx hir::Expr<'tcx>,
args: &'tcx [hir::Expr<'tcx>],
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
- let rcvr = &args[0];
let rcvr_t = self.check_expr(&rcvr);
// no need to check for bot/err -- callee does that
- let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t);
+ let rcvr_t = self.structurally_resolved_type(rcvr.span, rcvr_t);
let span = segment.ident.span;
let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) {
span,
rcvr_t,
segment.ident,
- SelfSource::MethodCall(&args[0]),
+ SelfSource::MethodCall(rcvr),
error,
- Some(args),
+ Some((rcvr, args)),
) {
err.emit();
}
};
// Call the generic checker.
- self.check_method_argument_types(
- span,
- expr,
- method,
- &args[1..],
- DontTupleArguments,
- expected,
- )
+ self.check_method_argument_types(span, expr, method, &args, DontTupleArguments, expected)
}
fn check_expr_cast(
}
}
+ pub fn require_type_is_sized_deferred(
+ &self,
+ ty: Ty<'tcx>,
+ span: Span,
+ code: traits::ObligationCauseCode<'tcx>,
+ ) {
+ if !ty.references_error() {
+ self.deferred_sized_obligations.borrow_mut().push((ty, span, code));
+ }
+ }
+
pub fn register_bound(
&self,
ty: Ty<'tcx>,
if found != self.tcx.types.unit {
return;
}
- if let ExprKind::MethodCall(path_segment, [rcvr, ..], _) = expr.kind {
+ if let ExprKind::MethodCall(path_segment, rcvr, ..) = expr.kind {
if self
.typeck_results
.borrow()
use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty, TypeSuperVisitable, TypeVisitor};
use rustc_session::Session;
use rustc_span::symbol::Ident;
-use rustc_span::{self, Span};
+use rustc_span::{self, sym, Span};
use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
use std::iter;
let minimum_input_count = expected_input_tys.len();
let provided_arg_count = provided_args.len();
+ let is_const_eval_select = matches!(fn_def_id, Some(def_id) if
+ self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
+ && self.tcx.is_intrinsic(def_id)
+ && self.tcx.item_name(def_id) == sym::const_eval_select);
+
// We introduce a helper function to demand that a given argument satisfy a given input
// This is more complicated than just checking type equality, as arguments could be coerced
// This version writes those types back so further type checking uses the narrowed types
return Compatibility::Incompatible(coerce_error);
}
+ // Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that
+ // the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed
+ // in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here.
+ //
+ // This check is here because there is currently no way to express a trait bound for `FnDef` types only.
+ if is_const_eval_select && (1..=2).contains(&idx) {
+ if let ty::FnDef(def_id, _) = checked_ty.kind() {
+ if idx == 1 && !self.tcx.is_const_fn_raw(*def_id) {
+ self.tcx
+ .sess
+ .struct_span_err(provided_arg.span, "this argument must be a `const fn`")
+ .help("consult the documentation on `const_eval_select` for more information")
+ .emit();
+ }
+ } else {
+ self.tcx
+ .sess
+ .struct_span_err(provided_arg.span, "this argument must be a function item")
+ .note(format!("expected a function item, found {checked_ty}"))
+ .help(
+ "consult the documentation on `const_eval_select` for more information",
+ )
+ .emit();
+ }
+ }
+
// 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
}
}
hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None, false),
- hir::ExprKind::MethodCall(path_segment, _, span) => {
+ 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())
.collect();
let callee_expr = match &call_expr.peel_blocks().kind {
hir::ExprKind::Call(callee, _) => Some(*callee),
- hir::ExprKind::MethodCall(_, callee, _) => {
+ hir::ExprKind::MethodCall(_, receiver, ..) => {
if let Some((DefKind::AssocFn, def_id)) =
self.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
&& let Some(assoc) = tcx.opt_associated_item(def_id)
&& assoc.fn_has_self_parameter
{
- Some(&callee[0])
+ Some(*receiver)
} else {
None
}
};
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(|_| fn_def_id
- .map_or("".to_string(), |fn_def_id| tcx.item_name(fn_def_id).to_string()))
- );
+ let (mut suggestion, suggestion_span) =
+ if let Some(call_span) = full_call_span.find_ancestor_inside(error_span) {
+ ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi()))
+ } else {
+ (
+ format!(
+ "{}(",
+ source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| {
+ fn_def_id.map_or("".to_string(), |fn_def_id| {
+ tcx.item_name(fn_def_id).to_string()
+ })
+ })
+ ),
+ error_span,
+ )
+ };
let mut needs_comma = false;
for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
if needs_comma {
}
suggestion += ")";
err.span_suggestion_verbose(
- error_span,
+ suggestion_span,
&suggestion_text,
suggestion,
Applicability::HasPlaceholders,
param,
*call_hir_id,
callee.span,
+ None,
args,
)
{
return true;
}
}
- // Notably, we only point to params that are local to the
- // item we're checking, since those are the ones we are able
- // to look in the final `hir::PathSegment` for. Everything else
- // would require a deeper search into the `qpath` than I think
- // is worthwhile.
- if let Some(param_to_point_at) = param_to_point_at
- && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
- {
- return true;
- }
+ }
+ // Notably, we only point to params that are local to the
+ // item we're checking, since those are the ones we are able
+ // to look in the final `hir::PathSegment` for. Everything else
+ // would require a deeper search into the `qpath` than I think
+ // is worthwhile.
+ if let Some(param_to_point_at) = param_to_point_at
+ && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
+ {
+ return true;
}
}
- hir::ExprKind::MethodCall(segment, args, ..) => {
+ hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
.into_iter()
.flatten()
param,
hir_id,
segment.ident.span,
+ Some(receiver),
args,
) {
return true;
param_to_point_at: ty::GenericArg<'tcx>,
call_hir_id: hir::HirId,
callee_span: Span,
- args: &[hir::Expr<'tcx>],
+ receiver: Option<&'tcx hir::Expr<'tcx>>,
+ args: &'tcx [hir::Expr<'tcx>],
) -> bool {
let sig = self.tcx.fn_sig(def_id).skip_binder();
let args_referencing_param: Vec<_> = sig
.enumerate()
.filter(|(_, ty)| find_param_in_ty(**ty, param_to_point_at))
.collect();
-
// If there's one field that references the given generic, great!
- if let [(idx, _)] = args_referencing_param.as_slice() && let Some(arg) = args.get(*idx) {
+ if let [(idx, _)] = args_referencing_param.as_slice()
+ && let Some(arg) = receiver
+ .map_or(args.get(*idx), |rcvr| if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }) {
error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span);
error.obligation.cause.map_code(|parent_code| {
ObligationCauseCode::FunctionArgumentObligation {
use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty};
use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
+ pub(crate) fn suggest_copied_or_cloned(
+ &self,
+ diag: &mut Diagnostic,
+ expr: &hir::Expr<'_>,
+ expr_ty: Ty<'tcx>,
+ expected_ty: Ty<'tcx>,
+ ) {
+ let ty::Adt(adt_def, substs) = expr_ty.kind() else { return; };
+ let ty::Adt(expected_adt_def, expected_substs) = expected_ty.kind() else { return; };
+ if adt_def != expected_adt_def {
+ return;
+ }
+
+ let mut suggest_copied_or_cloned = || {
+ let expr_inner_ty = substs.type_at(0);
+ let expected_inner_ty = expected_substs.type_at(0);
+ if let ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
+ && self.can_eq(self.param_env, *ty, expected_inner_ty).is_ok()
+ {
+ let def_path = self.tcx.def_path_str(adt_def.did());
+ if self.type_is_copy_modulo_regions(self.param_env, *ty, expr.span) {
+ diag.span_suggestion_verbose(
+ expr.span.shrink_to_hi(),
+ format!(
+ "use `{def_path}::copied` to copy the value inside the `{def_path}`"
+ ),
+ ".copied()",
+ Applicability::MachineApplicable,
+ );
+ } else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
+ && rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
+ self,
+ self.param_env,
+ *ty,
+ clone_did,
+ expr.span
+ )
+ {
+ diag.span_suggestion_verbose(
+ expr.span.shrink_to_hi(),
+ format!(
+ "use `{def_path}::cloned` to clone the value inside the `{def_path}`"
+ ),
+ ".cloned()",
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+ };
+
+ if let Some(result_did) = self.tcx.get_diagnostic_item(sym::Result)
+ && adt_def.did() == result_did
+ // Check that the error types are equal
+ && self.can_eq(self.param_env, substs.type_at(1), expected_substs.type_at(1)).is_ok()
+ {
+ suggest_copied_or_cloned();
+ } else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option)
+ && adt_def.did() == option_did
+ {
+ suggest_copied_or_cloned();
+ }
+ }
+
/// Suggest wrapping the block in square brackets instead of curly braces
/// in case the block was mistaken array syntax, e.g. `{ 1 }` -> `[ 1 ]`.
pub(crate) fn suggest_block_to_brackets(
found_ty: Ty<'tcx>,
expr: &hir::Expr<'_>,
) {
- let hir::ExprKind::MethodCall(segment, &[ref callee_expr], _) = expr.kind else { return; };
+ let hir::ExprKind::MethodCall(segment, callee_expr, &[], _) = expr.kind else { return; };
let Some(clone_trait_did) = self.tcx.lang_items().clone_trait() else { return; };
let ty::Ref(_, pointee_ty, _) = found_ty.kind() else { return };
let results = self.typeck_results.borrow();
}) {
self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)
} else {
- debug!("parent_node: {:?}", self.fcx.tcx.hir().find_parent_node(expr.hir_id));
- match self.fcx.tcx.hir().find_parent_node(expr.hir_id) {
+ let parent_expr = self
+ .fcx
+ .tcx
+ .hir()
+ .parent_iter(expr.hir_id)
+ .find(|(_, node)| matches!(node, hir::Node::Expr(_)))
+ .map(|(id, _)| id);
+ debug!("parent_expr: {:?}", parent_expr);
+ match parent_expr {
Some(parent) => Some(Scope { id: parent.local_id, data: ScopeData::Node }),
None => {
self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)
self.handle_uninhabited_return(expr);
}
- ExprKind::MethodCall(_, exprs, _) => {
+ ExprKind::MethodCall(_, receiver, exprs, _) => {
+ self.visit_expr(receiver);
for expr in exprs {
self.visit_expr(expr);
}
bk: rustc_middle::ty::BorrowKind,
) {
debug!(
- "borrow: place_with_id = {place_with_id:?}, diag_expr_id={diag_expr_id:?}, \
- borrow_kind={bk:?}"
+ "borrow: place_with_id = {place_with_id:#?}, diag_expr_id={diag_expr_id:#?}, \
+ borrow_kind={bk:#?}"
);
self.borrow_place(place_with_id);
pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,
+ // Some additional `Sized` obligations badly affect type inference.
+ // These obligations are added in a later stage of typeck.
+ // Removing these may also cause additional complications, see #101066.
+ pub(super) deferred_sized_obligations:
+ RefCell<Vec<(Ty<'tcx>, Span, traits::ObligationCauseCode<'tcx>)>>,
+
// When we process a call like `c()` where `c` is a closure type,
// we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
// `FnOnce` closure. In that case, we defer full resolution of the
infcx,
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
locals: RefCell::new(Default::default()),
+ deferred_sized_obligations: RefCell::new(Vec::new()),
deferred_call_resolutions: RefCell::new(Default::default()),
deferred_cast_checks: RefCell::new(Vec::new()),
deferred_transmute_checks: RefCell::new(Vec::new()),
if precise {
let args = args
.iter()
- .skip(1)
.map(|arg| {
let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
format!(
use rustc_middle::traits::util::supertraits;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
use rustc_middle::ty::print::with_crate_prefix;
-use rustc_middle::ty::ToPolyTraitRef;
use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Symbol;
use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
use std::cmp::Ordering;
use std::iter;
-use super::probe::{Mode, ProbeScope};
+use super::probe::{IsSuggestion, Mode, ProbeScope};
use super::{CandidateSource, MethodError, NoMatchData};
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
item_name: Ident,
source: SelfSource<'tcx>,
error: MethodError<'tcx>,
- args: Option<&'tcx [hir::Expr<'tcx>]>,
+ args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
// Avoid suggestions when we don't know what's going on.
if rcvr_ty.references_error() {
span,
rcvr_ty,
item_name,
- args.map(|args| args.len()),
+ args.map(|(_, args)| args.len() + 1),
source,
out_of_scope_traits,
&unsatisfied_predicates,
}
}
+ self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
+
return Some(err);
}
}
}
+ fn check_for_deref_method(
+ &self,
+ err: &mut Diagnostic,
+ self_source: SelfSource<'tcx>,
+ rcvr_ty: Ty<'tcx>,
+ item_name: Ident,
+ ) {
+ let SelfSource::QPath(ty) = self_source else { return; };
+ for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
+ if let Ok(pick) = self.probe_for_name(
+ ty.span,
+ Mode::Path,
+ item_name,
+ IsSuggestion(true),
+ deref_ty,
+ ty.hir_id,
+ ProbeScope::TraitsInScope,
+ ) {
+ if deref_ty.is_suggestable(self.tcx, true)
+ // If this method receives `&self`, then the provided
+ // argument _should_ coerce, so it's valid to suggest
+ // just changing the path.
+ && pick.item.fn_has_self_parameter
+ && let Some(self_ty) =
+ self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
+ && self_ty.is_ref()
+ {
+ let suggested_path = match deref_ty.kind() {
+ ty::Bool
+ | ty::Char
+ | ty::Int(_)
+ | ty::Uint(_)
+ | ty::Float(_)
+ | ty::Adt(_, _)
+ | ty::Str
+ | ty::Projection(_)
+ | ty::Param(_) => format!("{deref_ty}"),
+ _ => format!("<{deref_ty}>"),
+ };
+ err.span_suggestion_verbose(
+ ty.span,
+ format!("the function `{item_name}` is implemented on `{deref_ty}`"),
+ suggested_path,
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ err.span_note(
+ ty.span,
+ format!("the function `{item_name}` is implemented on `{deref_ty}`"),
+ );
+ }
+ return;
+ }
+ }
+ }
+
/// Print out the type for use in value namespace.
fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
match ty.kind() {
fn print_disambiguation_help<'tcx>(
item_name: Ident,
- args: Option<&'tcx [hir::Expr<'tcx>]>,
+ args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
err: &mut Diagnostic,
trait_name: String,
rcvr_ty: Ty<'_>,
fn_has_self_parameter: bool,
) {
let mut applicability = Applicability::MachineApplicable;
- let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
+ let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
let args = format!(
"({}{})",
if rcvr_ty.is_region_ptr() {
} else {
""
},
- args.iter()
+ std::iter::once(receiver)
+ .chain(args.iter())
.map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
applicability = Applicability::HasPlaceholders;
"_".to_owned()
fcx.resolve_rvalue_scopes(def_id.to_def_id());
fcx.resolve_generator_interiors(def_id.to_def_id());
+ for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
+ let ty = fcx.normalize_ty(span, ty);
+ fcx.require_type_is_sized(ty, span, code);
+ }
+
fcx.select_all_obligations_or_error();
if !fcx.infcx.is_tainted_by_errors() {
)
.is_ok()
{
- // Suppress this error, since we already emitted
- // a deref suggestion in check_overloaded_binop
- err.downgrade_to_delayed_bug();
+ // If LHS += RHS is an error, but *LHS += RHS is successful, then we will have
+ // emitted a better suggestion during error handling in check_overloaded_binop.
+ if self
+ .lookup_op_method(
+ lhs_ty,
+ Some(rhs_ty),
+ Some(rhs),
+ Op::Binary(op, IsAssign::Yes),
+ expected,
+ )
+ .is_err()
+ {
+ err.downgrade_to_delayed_bug();
+ } else {
+ // Otherwise, it's valid to suggest dereferencing the LHS here.
+ err.span_suggestion_verbose(
+ lhs.span.shrink_to_lo(),
+ "consider dereferencing the left-hand side of this operation",
+ "*",
+ Applicability::MaybeIncorrect,
+ );
+ }
}
}
});
tcx: TyCtxt<'_>,
closure_id: hir::HirId,
) -> bool {
+ if tcx.sess.rust_2021() {
+ return false;
+ }
+
let (level, _) =
tcx.lint_level_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id);
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
match ty.kind {
hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments {
- [s] => s.res.and_then(|r| r.opt_def_id()) == Some(trait_def_id.to_def_id()),
+ [s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()),
_ => false,
},
_ => false,
use rustc_errors::{Applicability, StashKey};
use rustc_hir as hir;
-use rustc_hir::def::Res;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit;
use rustc_hir::intravisit::Visitor;
args.args
.iter()
.filter(|arg| arg.is_ty_or_const())
- .position(|arg| arg.id() == hir_id)
+ .position(|arg| arg.hir_id() == hir_id)
})
.unwrap_or_else(|| {
bug!("no arg matching AnonConst in segment");
args.args
.iter()
.filter(|arg| arg.is_ty_or_const())
- .position(|arg| arg.id() == hir_id)
+ .position(|arg| arg.hir_id() == hir_id)
})
.unwrap_or_else(|| {
bug!("no arg matching AnonConst in segment");
args.args
.iter()
.filter(|arg| arg.is_ty_or_const())
- .position(|arg| arg.id() == hir_id)
+ .position(|arg| arg.hir_id() == hir_id)
.map(|index| (index, seg)).or_else(|| args.bindings
.iter()
.filter_map(TypeBinding::opt_const)
return None;
};
- // Try to use the segment resolution if it is valid, otherwise we
- // default to the path resolution.
- let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
- let generics = match tcx.res_generics_def_id(res) {
+ let generics = match tcx.res_generics_def_id(segment.res) {
Some(def_id) => tcx.generics_of(def_id),
None => {
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
- &format!("unexpected anon const res {:?} in path: {:?}", res, path),
+ &format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
);
return None;
}
.iter()
.filter_map(|seg| seg.args)
.flat_map(|args| args.args)
- .any(|arg| arg.id() == arg_id)
+ .any(|arg| arg.hir_id() == arg_id)
};
let mut arg_path = None;
pat.walk(|pat| match pat.kind {
self.consume_exprs(args);
}
- hir::ExprKind::MethodCall(.., args, _) => {
+ hir::ExprKind::MethodCall(.., receiver, args, _) => {
// callee.m(args)
+ self.consume_expr(receiver);
self.consume_exprs(args);
}
fn check_for_entry_fn(tcx: TyCtxt<'_>) {
match tcx.entry_fn(()) {
- Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
+ Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
_ => {}
}
// Creates lifetime name suggestions from the lifetime parameter names
fn get_lifetime_args_suggestions_from_param_names(
&self,
- path_hir_id: Option<hir::HirId>,
+ path_hir_id: hir::HirId,
num_params_to_take: usize,
) -> String {
debug!(?path_hir_id);
- if let Some(path_hir_id) = path_hir_id {
- let mut ret = Vec::new();
- for (id, node) in self.tcx.hir().parent_iter(path_hir_id) {
- debug!(?id);
- let params = if let Some(generics) = node.generics() {
- generics.params
- } else if let hir::Node::Ty(ty) = node
- && let hir::TyKind::BareFn(bare_fn) = ty.kind
- {
- bare_fn.generic_params
- } else {
- &[]
- };
- ret.extend(params.iter().filter_map(|p| {
- let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
- = p.kind
- else { return None };
- let hir::ParamName::Plain(name) = p.name else { return None };
- Some(name.to_string())
- }));
- // Suggest `'static` when in const/static item-like.
- if let hir::Node::Item(hir::Item {
- kind: hir::ItemKind::Static { .. } | hir::ItemKind::Const { .. },
- ..
- })
- | hir::Node::TraitItem(hir::TraitItem {
- kind: hir::TraitItemKind::Const { .. },
- ..
- })
- | hir::Node::ImplItem(hir::ImplItem {
- kind: hir::ImplItemKind::Const { .. },
- ..
- })
- | hir::Node::ForeignItem(hir::ForeignItem {
- kind: hir::ForeignItemKind::Static { .. },
- ..
- })
- | hir::Node::AnonConst(..) = node
- {
- ret.extend(
- std::iter::repeat("'static".to_owned())
- .take(num_params_to_take.saturating_sub(ret.len())),
- );
- }
- if ret.len() >= num_params_to_take {
- return ret[..num_params_to_take].join(", ");
- }
- // We cannot refer to lifetimes defined in an outer function.
- if let hir::Node::Item(_) = node {
- break;
- }
+ let mut ret = Vec::new();
+ for (id, node) in self.tcx.hir().parent_iter(path_hir_id) {
+ debug!(?id);
+ let params = if let Some(generics) = node.generics() {
+ generics.params
+ } else if let hir::Node::Ty(ty) = node
+ && let hir::TyKind::BareFn(bare_fn) = ty.kind
+ {
+ bare_fn.generic_params
+ } else {
+ &[]
+ };
+ ret.extend(params.iter().filter_map(|p| {
+ let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
+ = p.kind
+ else { return None };
+ let hir::ParamName::Plain(name) = p.name else { return None };
+ Some(name.to_string())
+ }));
+ // Suggest `'static` when in const/static item-like.
+ if let hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::Static { .. } | hir::ItemKind::Const { .. },
+ ..
+ })
+ | hir::Node::TraitItem(hir::TraitItem {
+ kind: hir::TraitItemKind::Const { .. },
+ ..
+ })
+ | hir::Node::ImplItem(hir::ImplItem {
+ kind: hir::ImplItemKind::Const { .. },
+ ..
+ })
+ | hir::Node::ForeignItem(hir::ForeignItem {
+ kind: hir::ForeignItemKind::Static { .. },
+ ..
+ })
+ | hir::Node::AnonConst(..) = node
+ {
+ ret.extend(
+ std::iter::repeat("'static".to_owned())
+ .take(num_params_to_take.saturating_sub(ret.len())),
+ );
+ }
+ if ret.len() >= num_params_to_take {
+ return ret[..num_params_to_take].join(", ");
+ }
+ // We cannot refer to lifetimes defined in an outer function.
+ if let hir::Node::Item(_) = node {
+ break;
}
}
num = num_trait_generics_except_self,
);
- if let Some(hir_id) = self.path_segment.hir_id
- && let Some(parent_node) = self.tcx.hir().find_parent_node(hir_id)
+ if let Some(parent_node) = self.tcx.hir().find_parent_node(self.path_segment.hir_id)
&& let Some(parent_node) = self.tcx.hir().find(parent_node)
&& let hir::Node::Expr(expr) = parent_node {
match expr.kind {
num_assoc_fn_excess_args: usize,
num_trait_generics_except_self: usize,
) {
- if let hir::ExprKind::MethodCall(_, args, _) = expr.kind {
- assert_eq!(args.len(), 1);
+ if let hir::ExprKind::MethodCall(_, receiver, args, ..) = expr.kind {
+ assert_eq!(args.len(), 0);
if num_assoc_fn_excess_args == num_trait_generics_except_self {
if let Some(gen_args) = self.gen_args.span_ext()
&& let Ok(gen_args) = self.tcx.sess.source_map().span_to_snippet(gen_args)
- && let Ok(args) = self.tcx.sess.source_map().span_to_snippet(args[0].span) {
- let sugg = format!("{}::{}::{}({})", self.tcx.item_name(trait_), gen_args, self.tcx.item_name(self.def_id), args);
+ && let Ok(receiver) = self.tcx.sess.source_map().span_to_snippet(receiver.span) {
+ let sugg = format!("{}::{}::{}({})", self.tcx.item_name(trait_), gen_args, self.tcx.item_name(self.def_id), receiver);
err.span_suggestion(expr.span, msg, sugg, Applicability::MaybeIncorrect);
}
}
/// A iterator for deduping the key of a sorted iterator.
/// When encountering the duplicated key, only the last key-value pair is yielded.
///
-/// Used by [`BTreeMap::bulk_build_from_sorted_iter`].
+/// Used by [`BTreeMap::bulk_build_from_sorted_iter`][1].
+///
+/// [1]: crate::collections::BTreeMap::bulk_build_from_sorted_iter
pub struct DedupSortedIter<K, V, I>
where
I: Iterator<Item = (K, V)>,
#![feature(ptr_metadata)]
#![feature(ptr_sub_ptr)]
#![feature(receiver_trait)]
+#![feature(saturating_int_impl)]
#![feature(set_ptr_value)]
#![feature(slice_from_ptr_range)]
#![feature(slice_group_by)]
+use core::num::{Saturating, Wrapping};
+
use crate::boxed::Box;
#[rustc_specialization_trait]
NonZeroUsize,
NonZeroIsize,
);
+
+unsafe impl<T: IsZero> IsZero for Wrapping<T> {
+ #[inline]
+ fn is_zero(&self) -> bool {
+ self.0.is_zero()
+ }
+}
+
+unsafe impl<T: IsZero> IsZero for Saturating<T> {
+ #[inline]
+ fn is_zero(&self) -> bool {
+ self.0.is_zero()
+ }
+}
-Subproject commit 4e5a3f72929f152752d5659e95bb15c8f6b41eff
+Subproject commit 07872f28cd8a65c3c7428811548dc85f1f2fb05b
/// assert!(!'ä¸'.is_lowercase());
/// assert!(!' '.is_lowercase());
/// ```
+ ///
+ /// In a const context:
+ ///
+ /// ```
+ /// #![feature(const_unicode_case_lookup)]
+ /// const CAPITAL_DELTA_IS_LOWERCASE: bool = 'Δ'.is_lowercase();
+ /// assert!(!CAPITAL_DELTA_IS_LOWERCASE);
+ /// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
#[inline]
- pub fn is_lowercase(self) -> bool {
+ pub const fn is_lowercase(self) -> bool {
match self {
'a'..='z' => true,
c => c > '\x7f' && unicode::Lowercase(c),
/// assert!(!'ä¸'.is_uppercase());
/// assert!(!' '.is_uppercase());
/// ```
+ ///
+ /// In a const context:
+ ///
+ /// ```
+ /// #![feature(const_unicode_case_lookup)]
+ /// const CAPITAL_DELTA_IS_UPPERCASE: bool = 'Δ'.is_uppercase();
+ /// assert!(CAPITAL_DELTA_IS_UPPERCASE);
+ /// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
#[inline]
- pub fn is_uppercase(self) -> bool {
+ pub const fn is_uppercase(self) -> bool {
match self {
'A'..='Z' => true,
c => c > '\x7f' && unicode::Uppercase(c),
)]
#![allow(missing_docs)]
-use crate::marker::{Destruct, DiscriminantKind};
+#[cfg(bootstrap)]
+use crate::marker::Destruct;
+use crate::marker::DiscriminantKind;
use crate::mem;
// These imports are used for simplifying intra-doc links
/// `ptr` must point to a vtable.
/// The intrinsic will return the alignment stored in that vtable.
pub fn vtable_align(ptr: *const ()) -> usize;
+
+ /// Selects which function to call depending on the context.
+ ///
+ /// If this function is evaluated at compile-time, then a call to this
+ /// intrinsic will be replaced with a call to `called_in_const`. It gets
+ /// replaced with a call to `called_at_rt` otherwise.
+ ///
+ /// # Type Requirements
+ ///
+ /// The two functions must be both function items. They cannot be function
+ /// pointers or closures. The first function must be a `const fn`.
+ ///
+ /// `arg` will be the tupled arguments that will be passed to either one of
+ /// the two functions, therefore, both functions must accept the same type of
+ /// arguments. Both functions must return RET.
+ ///
+ /// # Safety
+ ///
+ /// The two functions must behave observably equivalent. Safe code in other
+ /// crates may assume that calling a `const fn` at compile-time and at run-time
+ /// produces the same result. A function that produces a different result when
+ /// evaluated at run-time, or has any other observable side-effects, is
+ /// *unsound*.
+ ///
+ /// Here is an example of how this could cause a problem:
+ /// ```no_run
+ /// #![feature(const_eval_select)]
+ /// #![feature(core_intrinsics)]
+ /// use std::hint::unreachable_unchecked;
+ /// use std::intrinsics::const_eval_select;
+ ///
+ /// // Crate A
+ /// pub const fn inconsistent() -> i32 {
+ /// fn runtime() -> i32 { 1 }
+ /// const fn compiletime() -> i32 { 2 }
+ ///
+ /// unsafe {
+ // // âš This code violates the required equivalence of `compiletime`
+ /// // and `runtime`.
+ /// const_eval_select((), compiletime, runtime)
+ /// }
+ /// }
+ ///
+ /// // Crate B
+ /// const X: i32 = inconsistent();
+ /// let x = inconsistent();
+ /// if x != X { unsafe { unreachable_unchecked(); }}
+ /// ```
+ ///
+ /// This code causes Undefined Behavior when being run, since the
+ /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
+ /// which violates the principle that a `const fn` must behave the same at
+ /// compile-time and at run-time. The unsafe code in crate B is fine.
+ #[cfg(not(bootstrap))]
+ #[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
+ pub fn const_eval_select<ARG, F, G, RET>(arg: ARG, called_in_const: F, called_at_rt: G) -> RET
+ where
+ G: FnOnce<ARG, Output = RET>,
+ F: FnOnce<ARG, Output = RET>;
}
// Some functions are defined here because they accidentally got made
/// Check that the preconditions of an unsafe function are followed, if debug_assertions are on,
/// and only at runtime.
///
+/// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)`
+/// where the names specified will be moved into the macro as captured variables, and defines an item
+/// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics
+/// for the function declaractions and can be omitted if there is no generics.
+///
/// # Safety
///
/// Invoking this macro is only sound if the following code is already UB when the passed
/// the occasional mistake, and this check should help them figure things out.
#[allow_internal_unstable(const_eval_select)] // permit this to be called in stably-const fn
macro_rules! assert_unsafe_precondition {
- ($e:expr) => {
+ ($([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr) => {
if cfg!(debug_assertions) {
- // Use a closure so that we can capture arbitrary expressions from the invocation
- let runtime = || {
+ // allow non_snake_case to allow capturing const generics
+ #[allow(non_snake_case)]
+ #[inline(always)]
+ fn runtime$(<$($tt)*>)?($($i:$ty),*) {
if !$e {
// abort instead of panicking to reduce impact on code size
::core::intrinsics::abort();
}
- };
- const fn comptime() {}
+ }
+ #[allow(non_snake_case)]
+ const fn comptime$(<$($tt)*>)?($(_:$ty),*) {}
- ::core::intrinsics::const_eval_select((), comptime, runtime);
+ ::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime);
}
};
}
// SAFETY: the safety contract for `copy_nonoverlapping` must be
// upheld by the caller.
unsafe {
- assert_unsafe_precondition!(
+ assert_unsafe_precondition!([T](src: *const T, dst: *mut T, count: usize) =>
is_aligned_and_not_null(src)
&& is_aligned_and_not_null(dst)
&& is_nonoverlapping(src, dst, count)
// SAFETY: the safety contract for `copy` must be upheld by the caller.
unsafe {
- assert_unsafe_precondition!(is_aligned_and_not_null(src) && is_aligned_and_not_null(dst));
+ assert_unsafe_precondition!([T](src: *const T, dst: *mut T) =>
+ is_aligned_and_not_null(src) && is_aligned_and_not_null(dst));
copy(src, dst, count)
}
}
// SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
unsafe {
- assert_unsafe_precondition!(is_aligned_and_not_null(dst));
+ assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst));
write_bytes(dst, val, count)
}
}
-/// Selects which function to call depending on the context.
-///
-/// If this function is evaluated at compile-time, then a call to this
-/// intrinsic will be replaced with a call to `called_in_const`. It gets
-/// replaced with a call to `called_at_rt` otherwise.
-///
-/// # Type Requirements
-///
-/// The two functions must be both function items. They cannot be function
-/// pointers or closures.
-///
-/// `arg` will be the arguments that will be passed to either one of the
-/// two functions, therefore, both functions must accept the same type of
-/// arguments. Both functions must return RET.
-///
-/// # Safety
-///
-/// The two functions must behave observably equivalent. Safe code in other
-/// crates may assume that calling a `const fn` at compile-time and at run-time
-/// produces the same result. A function that produces a different result when
-/// evaluated at run-time, or has any other observable side-effects, is
-/// *unsound*.
-///
-/// Here is an example of how this could cause a problem:
-/// ```no_run
-/// #![feature(const_eval_select)]
-/// #![feature(core_intrinsics)]
-/// use std::hint::unreachable_unchecked;
-/// use std::intrinsics::const_eval_select;
-///
-/// // Crate A
-/// pub const fn inconsistent() -> i32 {
-/// fn runtime() -> i32 { 1 }
-/// const fn compiletime() -> i32 { 2 }
-///
-/// unsafe {
-// // âš This code violates the required equivalence of `compiletime`
-/// // and `runtime`.
-/// const_eval_select((), compiletime, runtime)
-/// }
-/// }
-///
-/// // Crate B
-/// const X: i32 = inconsistent();
-/// let x = inconsistent();
-/// if x != X { unsafe { unreachable_unchecked(); }}
-/// ```
-///
-/// This code causes Undefined Behavior when being run, since the
-/// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
-/// which violates the principle that a `const fn` must behave the same at
-/// compile-time and at run-time. The unsafe code in crate B is fine.
+#[cfg(bootstrap)]
#[unstable(
feature = "const_eval_select",
issue = "none",
called_at_rt.call_once(arg)
}
+#[cfg(bootstrap)]
#[unstable(
feature = "const_eval_select",
issue = "none",
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![allow(explicit_outlives_requirements)]
+#![allow(incomplete_features)]
//
// Library features:
#![feature(const_align_offset)]
#![feature(const_type_id)]
#![feature(const_type_name)]
#![feature(const_default_impls)]
+#![feature(const_unicode_case_lookup)]
#![feature(const_unsafecell_get_mut)]
#![feature(core_panic)]
#![feature(duration_consts_float)]
//
// Language features:
#![feature(abi_unadjusted)]
+#![feature(adt_const_params)]
#![feature(allow_internal_unsafe)]
#![feature(allow_internal_unstable)]
#![feature(associated_type_bounds)]
/// any value of type `Self` are safely transmutable into a value of type `Dst`, in a given `Context`,
/// notwithstanding whatever safety checks you have asked the compiler to [`Assume`] are satisfied.
#[unstable(feature = "transmutability", issue = "99571")]
-#[lang = "transmute_trait"]
+#[cfg_attr(not(bootstrap), lang = "transmute_trait")]
#[rustc_on_unimplemented(
message = "`{Src}` cannot be safely transmuted into `{Self}` in the defining scope of `{Context}`.",
label = "`{Src}` cannot be safely transmuted into `{Self}` in the defining scope of `{Context}`."
)]
-pub unsafe trait BikeshedIntrinsicFrom<
- Src,
- Context,
- const ASSUME_ALIGNMENT: bool,
- const ASSUME_LIFETIMES: bool,
- const ASSUME_VALIDITY: bool,
- const ASSUME_VISIBILITY: bool,
-> where
+pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
+where
Src: ?Sized,
{
}
/// What transmutation safety conditions shall the compiler assume that *you* are checking?
#[unstable(feature = "transmutability", issue = "99571")]
+#[cfg_attr(not(bootstrap), lang = "transmute_opts")]
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct Assume {
/// When `true`, the compiler assumes that *you* are ensuring (either dynamically or statically) that
/// that violates Rust's memory model.
pub lifetimes: bool,
+ /// When `true`, the compiler assumes that *you* have ensured that it is safe for you to violate the
+ /// type and field privacy of the destination type (and sometimes of the source type, too).
+ pub safety: bool,
+
/// When `true`, the compiler assumes that *you* are ensuring that the source type is actually a valid
/// instance of the destination type.
pub validity: bool,
+}
- /// When `true`, the compiler assumes that *you* have ensured that it is safe for you to violate the
- /// type and field privacy of the destination type (and sometimes of the source type, too).
- pub visibility: bool,
+impl Assume {
+ /// Do not assume that *you* have ensured any safety properties are met.
+ #[unstable(feature = "transmutability", issue = "99571")]
+ pub const NOTHING: Self =
+ Self { alignment: false, lifetimes: false, safety: false, validity: false };
+
+ /// Assume only that alignment conditions are met.
+ #[unstable(feature = "transmutability", issue = "99571")]
+ pub const ALIGNMENT: Self = Self { alignment: true, ..Self::NOTHING };
+
+ /// Assume only that lifetime conditions are met.
+ #[unstable(feature = "transmutability", issue = "99571")]
+ pub const LIFETIMES: Self = Self { lifetimes: true, ..Self::NOTHING };
+
+ /// Assume only that safety conditions are met.
+ #[unstable(feature = "transmutability", issue = "99571")]
+ pub const SAFETY: Self = Self { safety: true, ..Self::NOTHING };
+
+ /// Assume only that dynamically-satisfiable validity conditions are met.
+ #[unstable(feature = "transmutability", issue = "99571")]
+ pub const VALIDITY: Self = Self { validity: true, ..Self::NOTHING };
+
+ /// Assume both `self` and `other_assumptions`.
+ #[unstable(feature = "transmutability", issue = "99571")]
+ pub const fn and(self, other_assumptions: Self) -> Self {
+ Self {
+ alignment: self.alignment || other_assumptions.alignment,
+ lifetimes: self.lifetimes || other_assumptions.lifetimes,
+ safety: self.safety || other_assumptions.safety,
+ validity: self.validity || other_assumptions.validity,
+ }
+ }
+
+ /// Assume `self`, excepting `other_assumptions`.
+ #[unstable(feature = "transmutability", issue = "99571")]
+ pub const fn but_not(self, other_assumptions: Self) -> Self {
+ Self {
+ alignment: self.alignment && !other_assumptions.alignment,
+ lifetimes: self.lifetimes && !other_assumptions.lifetimes,
+ safety: self.safety && !other_assumptions.safety,
+ validity: self.validity && !other_assumptions.validity,
+ }
+ }
+}
+
+// FIXME(jswrenn): This const op is not actually usable. Why?
+// https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926
+#[unstable(feature = "transmutability", issue = "99571")]
+#[rustc_const_unstable(feature = "transmutability", issue = "99571")]
+impl const core::ops::Add for Assume {
+ type Output = Assume;
+
+ fn add(self, other_assumptions: Assume) -> Assume {
+ self.and(other_assumptions)
+ }
+}
+
+// FIXME(jswrenn): This const op is not actually usable. Why?
+// https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926
+#[unstable(feature = "transmutability", issue = "99571")]
+#[rustc_const_unstable(feature = "transmutability", issue = "99571")]
+impl const core::ops::Sub for Assume {
+ type Output = Assume;
+
+ fn sub(self, other_assumptions: Assume) -> Assume {
+ self.but_not(other_assumptions)
+ }
}
#[inline]
pub(crate) const unsafe fn new_unchecked(align: usize) -> Self {
// SAFETY: Precondition passed to the caller.
- unsafe { assert_unsafe_precondition!(align.is_power_of_two()) };
+ unsafe { assert_unsafe_precondition!((align: usize) => align.is_power_of_two()) };
// SAFETY: By precondition, this must be a power of two, and
// our variants encompass all possible powers of two.
}
}
}
- // 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) };
+
+ #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491
+ fn rt_f32_to_u32(x: f32) -> u32 {
+ // SAFETY: `u32` is a plain old datatype so we can always... uh...
+ // ...look, just pretend you forgot what you just read.
+ // Stability concerns.
+ unsafe { mem::transmute(x) }
+ }
// 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) }
}
}
}
}
- // 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) };
+
+ #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491
+ fn rt_u32_to_f32(x: u32) -> f32 {
+ // SAFETY: `u32` is a plain old datatype so we can always... uh...
+ // ...look, just pretend you forgot what you just read.
+ // Stability concerns.
+ unsafe { mem::transmute(x) }
+ }
// 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) }
}
}
}
}
- // 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) };
+
+ #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491
+ fn rt_f64_to_u64(rt: f64) -> u64 {
+ // SAFETY: `u64` is a plain old datatype so we can always... uh...
+ // ...look, just pretend you forgot what you just read.
+ // Stability concerns.
+ 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) }
}
}
}
}
- // 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) };
+
+ #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491
+ fn rt_u64_to_f64(rt: u64) -> f64 {
+ // SAFETY: `u64` is a plain old datatype so we can always... uh...
+ // ...look, just pretend you forgot what you just read.
+ // Stability concerns.
+ 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) }
}
pub const unsafe fn new_unchecked(n: $Int) -> Self {
// SAFETY: this is guaranteed to be safe by the caller.
unsafe {
- core::intrinsics::assert_unsafe_precondition!(n != 0);
+ core::intrinsics::assert_unsafe_precondition!((n: $Int) => n != 0);
Self(n)
}
}
impl<T> Bound<T> {
/// Converts from `&Bound<T>` to `Bound<&T>`.
#[inline]
- #[unstable(feature = "bound_as_ref", issue = "80996")]
+ #[stable(feature = "bound_as_ref_shared", since = "CURRENT_RUSTC_VERSION")]
pub fn as_ref(&self) -> Bound<&T> {
match *self {
Included(ref x) => Included(x),
/// Every `Try` type needs to be recreatable from its own associated
/// `Residual` type, but can also have additional `FromResidual` implementations
/// to support interconversion with other `Try` types.
-#[rustc_on_unimplemented(
+#[cfg_attr(not(bootstrap), rustc_on_unimplemented(
+ on(
+ all(
+ from_desugaring = "QuestionMark",
+ _Self = "std::result::Result<T, E>",
+ R = "std::option::Option<std::convert::Infallible>"
+ ),
+ message = "the `?` operator can only be used on `Result`s, not `Option`s, \
+ in {ItemContext} that returns `Result`",
+ label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`",
+ parent_label = "this function returns a `Result`"
+ ),
+ on(
+ all(
+ from_desugaring = "QuestionMark",
+ _Self = "std::result::Result<T, E>",
+ ),
+ // There's a special error message in the trait selection code for
+ // `From` in `?`, so this is not shown for result-in-result errors,
+ // and thus it can be phrased more strongly than `ControlFlow`'s.
+ message = "the `?` operator can only be used on `Result`s \
+ in {ItemContext} that returns `Result`",
+ label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
+ parent_label = "this function returns a `Result`"
+ ),
+ on(
+ all(
+ from_desugaring = "QuestionMark",
+ _Self = "std::option::Option<T>",
+ R = "std::result::Result<T, E>",
+ ),
+ message = "the `?` operator can only be used on `Option`s, not `Result`s, \
+ in {ItemContext} that returns `Option`",
+ label = "use `.ok()?` if you want to discard the `{R}` error information",
+ parent_label = "this function returns an `Option`"
+ ),
+ on(
+ all(
+ from_desugaring = "QuestionMark",
+ _Self = "std::option::Option<T>",
+ ),
+ // `Option`-in-`Option` always works, as there's only one possible
+ // residual, so this can also be phrased strongly.
+ message = "the `?` operator can only be used on `Option`s \
+ in {ItemContext} that returns `Option`",
+ label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
+ parent_label = "this function returns an `Option`"
+ ),
+ on(
+ all(
+ from_desugaring = "QuestionMark",
+ _Self = "std::ops::ControlFlow<B, C>",
+ R = "std::ops::ControlFlow<B, C>",
+ ),
+ message = "the `?` operator in {ItemContext} that returns `ControlFlow<B, _>` \
+ can only be used on other `ControlFlow<B, _>`s (with the same Break type)",
+ label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
+ parent_label = "this function returns a `ControlFlow`",
+ note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
+ ),
+ on(
+ all(
+ from_desugaring = "QuestionMark",
+ _Self = "std::ops::ControlFlow<B, C>",
+ // `R` is not a `ControlFlow`, as that case was matched previously
+ ),
+ message = "the `?` operator can only be used on `ControlFlow`s \
+ in {ItemContext} that returns `ControlFlow`",
+ label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
+ parent_label = "this function returns a `ControlFlow`",
+ ),
+ on(
+ all(from_desugaring = "QuestionMark"),
+ message = "the `?` operator can only be used in {ItemContext} \
+ that returns `Result` or `Option` \
+ (or another type that implements `{FromResidual}`)",
+ label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
+ parent_label = "this function should return `Result` or `Option` to accept `?`"
+ ),
+))]
+#[cfg_attr(bootstrap, rustc_on_unimplemented(
on(
all(
from_desugaring = "QuestionMark",
label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
),
-)]
+))]
#[rustc_diagnostic_item = "FromResidual"]
#[unstable(feature = "try_trait_v2", issue = "84277")]
pub trait FromResidual<R = <Self as Try>::Residual> {
where
T: Sized,
{
+ let this = self;
// SAFETY: The comparison has no side-effects, and the intrinsic
// does this check internally in the CTFE implementation.
- unsafe { assert_unsafe_precondition!(self >= origin) };
+ unsafe {
+ assert_unsafe_precondition!([T](this: *const T, origin: *const T) => this >= origin)
+ };
let pointee_size = mem::size_of::<T>();
assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
// SAFETY: the caller must guarantee that `x` and `y` are
// valid for writes and properly aligned.
unsafe {
- assert_unsafe_precondition!(
+ assert_unsafe_precondition!([T](x: *mut T, y: *mut T, count: usize) =>
is_aligned_and_not_null(x)
&& is_aligned_and_not_null(y)
&& is_nonoverlapping(x, y, count)
// and cannot overlap `src` since `dst` must point to a distinct
// allocated object.
unsafe {
- assert_unsafe_precondition!(is_aligned_and_not_null(dst));
+ assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst));
mem::swap(&mut *dst, &mut src); // cannot overlap
}
src
pub unsafe fn read_volatile<T>(src: *const T) -> T {
// SAFETY: the caller must uphold the safety contract for `volatile_load`.
unsafe {
- assert_unsafe_precondition!(is_aligned_and_not_null(src));
+ assert_unsafe_precondition!([T](src: *const T) => is_aligned_and_not_null(src));
intrinsics::volatile_load(src)
}
}
pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
// SAFETY: the caller must uphold the safety contract for `volatile_store`.
unsafe {
- assert_unsafe_precondition!(is_aligned_and_not_null(dst));
+ assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst));
intrinsics::volatile_store(dst, src);
}
}
}
// FIXME const-hack
+#[track_caller]
fn slice_start_index_len_fail_rt(index: usize, len: usize) -> ! {
panic!("range start index {index} out of range for slice of length {len}");
}
+#[track_caller]
const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! {
panic!("slice start index is out of range for slice");
}
}
// FIXME const-hack
+#[track_caller]
fn slice_end_index_len_fail_rt(index: usize, len: usize) -> ! {
panic!("range end index {index} out of range for slice of length {len}");
}
+#[track_caller]
const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! {
panic!("slice end index is out of range for slice");
}
}
// FIXME const-hack
+#[track_caller]
fn slice_index_order_fail_rt(index: usize, end: usize) -> ! {
panic!("slice index starts at {index} but ends at {end}");
}
+#[track_caller]
const fn slice_index_order_fail_ct(_: usize, _: usize) -> ! {
panic!("slice index start is larger than end");
}
#[inline]
unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
+ let this = self;
// SAFETY: the caller guarantees that `slice` is not dangling, so it
// cannot be longer than `isize::MAX`. They also guarantee that
// `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
// so the call to `add` is safe.
unsafe {
- assert_unsafe_precondition!(self < slice.len());
+ assert_unsafe_precondition!([T](this: usize, slice: *const [T]) => this < slice.len());
slice.as_ptr().add(self)
}
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
+ let this = self;
// SAFETY: see comments for `get_unchecked` above.
unsafe {
- assert_unsafe_precondition!(self < slice.len());
+ assert_unsafe_precondition!([T](this: usize, slice: *mut [T]) => this < slice.len());
slice.as_mut_ptr().add(self)
}
}
#[inline]
unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+ let this = ops::Range { start: self.start, end: self.end };
// SAFETY: the caller guarantees that `slice` is not dangling, so it
// cannot be longer than `isize::MAX`. They also guarantee that
// `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
// so the call to `add` is safe.
unsafe {
- assert_unsafe_precondition!(self.end >= self.start && self.end <= slice.len());
+ assert_unsafe_precondition!([T](this: ops::Range<usize>, slice: *const [T]) =>
+ this.end >= this.start && this.end <= slice.len());
ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start)
}
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
+ let this = ops::Range { start: self.start, end: self.end };
// SAFETY: see comments for `get_unchecked` above.
unsafe {
- assert_unsafe_precondition!(self.end >= self.start && self.end <= slice.len());
+ assert_unsafe_precondition!([T](this: ops::Range<usize>, slice: *mut [T]) =>
+ this.end >= this.start && this.end <= slice.len());
ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start)
}
}
#[unstable(feature = "slice_swap_unchecked", issue = "88539")]
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
- let ptr = self.as_mut_ptr();
+ let this = self;
+ let ptr = this.as_mut_ptr();
// SAFETY: caller has to guarantee that `a < self.len()` and `b < self.len()`
unsafe {
- assert_unsafe_precondition!(a < self.len() && b < self.len());
+ assert_unsafe_precondition!([T](a: usize, b: usize, this: &mut [T]) => a < this.len() && b < this.len());
ptr::swap(ptr.add(a), ptr.add(b));
}
}
#[inline]
#[must_use]
pub unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
+ let this = self;
// SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
let new_len = unsafe {
- assert_unsafe_precondition!(N != 0 && self.len() % N == 0);
+ assert_unsafe_precondition!([T](this: &[T], N: usize) => N != 0 && this.len() % N == 0);
exact_div(self.len(), N)
};
// SAFETY: We cast a slice of `new_len * N` elements into
#[inline]
#[must_use]
pub unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
+ let this = &*self;
// SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
let new_len = unsafe {
- assert_unsafe_precondition!(N != 0 && self.len() % N == 0);
- exact_div(self.len(), N)
+ assert_unsafe_precondition!([T](this: &[T], N: usize) => N != 0 && this.len() % N == 0);
+ exact_div(this.len(), N)
};
// SAFETY: We cast a slice of `new_len * N` elements into
// a slice of `new_len` many `N` elements chunks.
// `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference
// is fine.
unsafe {
- assert_unsafe_precondition!(mid <= len);
+ assert_unsafe_precondition!((mid: usize, len: usize) => mid <= len);
(from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid))
}
}
pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
// SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
unsafe {
- assert_unsafe_precondition!(
+ assert_unsafe_precondition!([T](data: *const T, len: usize) =>
is_aligned_and_not_null(data)
&& crate::mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize
);
pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
unsafe {
- assert_unsafe_precondition!(
+ assert_unsafe_precondition!([T](data: *mut T, len: usize) =>
is_aligned_and_not_null(data)
&& crate::mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize
);
}
}
+#[track_caller]
const fn slice_error_fail_ct(_: &str, _: usize, _: usize) -> ! {
panic!("failed to slice string");
}
+#[track_caller]
fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! {
const MAX_DISPLAY_LENGTH: usize = 256;
let trunc_len = s.floor_char_boundary(MAX_DISPLAY_LENGTH);
///! This file is generated by src/tools/unicode-table-generator; do not edit manually!
+#[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
#[inline(always)]
-fn bitset_search<
+const fn bitset_search<
const N: usize,
const CHUNK_SIZE: usize,
const N1: usize,
let bucket_idx = (needle / 64) as usize;
let chunk_map_idx = bucket_idx / CHUNK_SIZE;
let chunk_piece = bucket_idx % CHUNK_SIZE;
- let chunk_idx = if let Some(&v) = chunk_idx_map.get(chunk_map_idx) {
- v
+ // FIXME: const-hack: Revert to `slice::get` after `const_slice_index`
+ // feature stabilizes.
+ let chunk_idx = if chunk_map_idx < chunk_idx_map.len() {
+ chunk_idx_map[chunk_map_idx]
} else {
return false;
};
let idx = bitset_chunk_idx[chunk_idx as usize][chunk_piece] as usize;
- let word = if let Some(word) = bitset_canonical.get(idx) {
- *word
+ // FIXME: const-hack: Revert to `slice::get` after `const_slice_index`
+ // feature stabilizes.
+ let word = if idx < bitset_canonical.len() {
+ bitset_canonical[idx]
} else {
let (real_idx, mapping) = bitset_canonicalized[idx - bitset_canonical.len()];
let mut word = bitset_canonical[real_idx as usize];
#[rustfmt::skip]
pub mod lowercase {
- static BITSET_CHUNKS_MAP: [u8; 123] = [
+ const BITSET_CHUNKS_MAP: &'static [u8; 123] = &[
14, 17, 0, 0, 9, 0, 0, 12, 13, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 4, 1, 0, 15, 0, 8, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0,
3, 0, 0, 7,
];
- static BITSET_INDEX_CHUNKS: [[u8; 16]; 19] = [
+ const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 19] = &[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 55, 0],
[16, 49, 2, 20, 66, 9, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[63, 39, 54, 12, 73, 61, 18, 1, 6, 62, 71, 19, 68, 69, 3, 44],
];
- static BITSET_CANONICAL: [u64; 55] = [
+ const BITSET_CANONICAL: &'static [u64; 55] = &[
0b0000000000000000000000000000000000000000000000000000000000000000,
0b1111111111111111110000000000000000000000000011111111111111111111,
0b1010101010101010101010101010101010101010101010101010100000000010,
0b1110011111111111111111111111111111111111111111110000000000000000,
0b1110101111000000000000000000000000001111111111111111111111111100,
];
- static BITSET_MAPPING: [(u8, u8); 20] = [
+ const BITSET_MAPPING: &'static [(u8, u8); 20] = &[
(0, 64), (1, 188), (1, 183), (1, 176), (1, 109), (1, 124), (1, 126), (1, 66), (1, 70),
(1, 77), (2, 146), (2, 144), (2, 83), (3, 12), (3, 6), (4, 156), (4, 78), (5, 187),
(6, 132), (7, 93),
];
- pub fn lookup(c: char) -> bool {
+ #[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
+ pub const fn lookup(c: char) -> bool {
super::bitset_search(
c as u32,
&BITSET_CHUNKS_MAP,
#[rustfmt::skip]
pub mod uppercase {
- static BITSET_CHUNKS_MAP: [u8; 125] = [
+ const BITSET_CHUNKS_MAP: &'static [u8; 125] = &[
12, 15, 6, 6, 0, 6, 6, 2, 4, 11, 6, 16, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 5, 6, 14, 6, 10, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 13, 6, 6,
6, 6, 9, 6, 3,
];
- static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [
+ const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 17] = &[
[43, 43, 5, 34, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 5, 1],
[43, 43, 5, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43],
[43, 43, 39, 43, 43, 43, 43, 43, 17, 17, 62, 17, 42, 29, 24, 23],
[57, 19, 2, 18, 10, 47, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43],
[57, 37, 17, 27, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43],
];
- static BITSET_CANONICAL: [u64; 43] = [
+ const BITSET_CANONICAL: &'static [u64; 43] = &[
0b0000011111111111111111111111111000000000000000000000000000000000,
0b0000000000111111111111111111111111111111111111111111111111111111,
0b0101010101010101010101010101010101010101010101010101010000000001,
0b1111011111111111000000000000000000000000000000000000000000000000,
0b1111111100000000111111110000000000111111000000001111111100000000,
];
- static BITSET_MAPPING: [(u8, u8); 25] = [
+ const BITSET_MAPPING: &'static [(u8, u8); 25] = &[
(0, 187), (0, 177), (0, 171), (0, 167), (0, 164), (0, 32), (0, 47), (0, 51), (0, 121),
(0, 117), (0, 109), (1, 150), (1, 148), (1, 142), (1, 134), (1, 131), (1, 64), (2, 164),
(2, 146), (2, 20), (3, 146), (3, 140), (3, 134), (4, 178), (4, 171),
];
- pub fn lookup(c: char) -> bool {
+ #[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
+ pub const fn lookup(c: char) -> bool {
super::bitset_search(
c as u32,
&BITSET_CHUNKS_MAP,
#![cfg_attr(feature = "as_crate", no_std)] // We are std!
-#![cfg_attr(
- feature = "as_crate",
- feature(platform_intrinsics),
- feature(portable_simd)
-)]
+#![cfg_attr(feature = "as_crate", feature(platform_intrinsics), feature(portable_simd))]
#[cfg(not(feature = "as_crate"))]
use core::simd;
#[cfg(feature = "as_crate")]
use super::*;
+use std::cell::Cell;
use std::marker::PhantomData;
// FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`.
) -> Buffer;
}
+thread_local! {
+ /// While running a proc-macro with the same-thread executor, this flag will
+ /// be set, forcing nested proc-macro invocations (e.g. due to
+ /// `TokenStream::expand_expr`) to be run using a cross-thread executor.
+ ///
+ /// This is required as the thread-local state in the proc_macro client does
+ /// not handle being re-entered, and will invalidate all `Symbol`s when
+ /// entering a nested macro.
+ static ALREADY_RUNNING_SAME_THREAD: Cell<bool> = Cell::new(false);
+}
+
+/// Keep `ALREADY_RUNNING_SAME_THREAD` (see also its documentation)
+/// set to `true`, preventing same-thread reentrance.
+struct RunningSameThreadGuard(());
+
+impl RunningSameThreadGuard {
+ fn new() -> Self {
+ let already_running = ALREADY_RUNNING_SAME_THREAD.replace(true);
+ assert!(
+ !already_running,
+ "same-thread nesting (\"reentrance\") of proc macro executions is not supported"
+ );
+ RunningSameThreadGuard(())
+ }
+}
+
+impl Drop for RunningSameThreadGuard {
+ fn drop(&mut self) {
+ ALREADY_RUNNING_SAME_THREAD.set(false);
+ }
+}
+
pub struct MaybeCrossThread<P> {
cross_thread: bool,
marker: PhantomData<P>,
run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer,
force_show_panics: bool,
) -> Buffer {
- if self.cross_thread {
+ if self.cross_thread || ALREADY_RUNNING_SAME_THREAD.get() {
<CrossThread<P>>::new().run_bridge_and_client(
dispatcher,
input,
run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer,
force_show_panics: bool,
) -> Buffer {
+ let _guard = RunningSameThreadGuard::new();
+
let mut dispatch = |buf| dispatcher.dispatch(buf);
run_client(BridgeConfig {
/// The default memory allocator provided by the operating system.
///
/// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows,
-/// plus related functions.
+/// plus related functions. However, it is not valid to mix use of the backing
+/// system allocator with `System`, as this implementation may include extra
+/// work, such as to serve alignment requests greater than the alignment
+/// provided directly by the backing system allocator.
///
/// This type implements the `GlobalAlloc` trait and Rust programs by default
/// work as if they had this definition:
///
/// If the returned iterator is dropped before being fully consumed, it
/// drops the remaining elements. The returned iterator keeps a mutable
- /// borrow on the vector to optimize its implementation.
+ /// borrow on the set to optimize its implementation.
///
/// # Examples
///
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
use crate::time::SystemTime;
-/// A reference to an open file on the filesystem.
+/// An object providing access to an open file on the filesystem.
///
/// An instance of a `File` can be read and/or written depending on what options
/// it was opened with. Files also implement [`Seek`] to alter the logical cursor
use crate::cell::{Cell, RefCell};
use crate::fmt;
use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
-use crate::pin::Pin;
use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sync::{Arc, Mutex, MutexGuard, OnceLock};
use crate::sys::stdio;
// FIXME: this should be LineWriter or BufWriter depending on the state of
// stdout (tty or not). Note that if this is not line buffered it
// should also flush-on-panic or some form of flush-on-abort.
- inner: Pin<&'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
+ inner: &'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>,
}
/// A locked reference to the [`Stdout`] handle.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdout() -> Stdout {
Stdout {
- inner: Pin::static_ref(&STDOUT).get_or_init_pin(
- || unsafe { ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw()))) },
- |mutex| unsafe { mutex.init() },
- ),
+ inner: STDOUT
+ .get_or_init(|| ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))),
}
}
+// Flush the data and disable buffering during shutdown
+// by replacing the line writer by one with zero
+// buffering capacity.
pub fn cleanup() {
- if let Some(instance) = STDOUT.get() {
- // Flush the data and disable buffering during shutdown
- // by replacing the line writer by one with zero
- // buffering capacity.
+ let mut initialized = false;
+ let stdout = STDOUT.get_or_init(|| {
+ initialized = true;
+ ReentrantMutex::new(RefCell::new(LineWriter::with_capacity(0, stdout_raw())))
+ });
+
+ if !initialized {
+ // The buffer was previously initialized, overwrite it here.
// We use try_lock() instead of lock(), because someone
// might have leaked a StdoutLock, which would
// otherwise cause a deadlock here.
- if let Some(lock) = Pin::static_ref(instance).try_lock() {
+ if let Some(lock) = stdout.try_lock() {
*lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
}
}
/// standard library or via raw Windows API calls, will fail.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stderr {
- inner: Pin<&'static ReentrantMutex<RefCell<StderrRaw>>>,
+ inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
}
/// A locked reference to the [`Stderr`] handle.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stderr() -> Stderr {
// Note that unlike `stdout()` we don't use `at_exit` here to register a
- // destructor. Stderr is not buffered , so there's no need to run a
+ // destructor. Stderr is not buffered, so there's no need to run a
// destructor for flushing the buffer
- static INSTANCE: OnceLock<ReentrantMutex<RefCell<StderrRaw>>> = OnceLock::new();
+ static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
+ ReentrantMutex::new(RefCell::new(stderr_raw()));
- Stderr {
- inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
- || unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) },
- |mutex| unsafe { mutex.init() },
- ),
- }
+ Stderr { inner: &INSTANCE }
}
impl Stderr {
#[cfg(target_os = "espidf")]
let cmd = libc::F_DUPFD;
- let fd = cvt(unsafe { libc::fcntl(self.as_raw_fd(), cmd, 0) })?;
+ // Avoid using file descriptors below 3 as they are used for stdio
+ let fd = cvt(unsafe { libc::fcntl(self.as_raw_fd(), cmd, 3) })?;
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
}
// Runs before `main`.
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
+//
+// # The `sigpipe` parameter
+//
+// Since 2014, the Rust runtime on Unix has set the `SIGPIPE` handler to
+// `SIG_IGN`. Applications have good reasons to want a different behavior
+// though, so there is a `#[unix_sigpipe = "..."]` attribute on `fn main()` that
+// can be used to select how `SIGPIPE` shall be setup (if changed at all) before
+// `fn main()` is called. See <https://github.com/rust-lang/rust/issues/97889>
+// for more info.
+//
+// The `sigpipe` parameter to this function gets its value via the code that
+// rustc generates to invoke `fn lang_start()`. The reason we have `sigpipe` for
+// all platforms and not only Unix, is because std is not allowed to have `cfg`
+// directives as this high level. See the module docs in
+// `src/tools/tidy/src/pal.rs` for more info. On all other platforms, `sigpipe`
+// has a value, but its value is ignored.
+//
+// Even though it is an `u8`, it only ever has 3 values. These are documented in
+// `compiler/rustc_session/src/config/sigpipe.rs`.
#[cfg_attr(test, allow(dead_code))]
-unsafe fn init(argc: isize, argv: *const *const u8) {
+unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
unsafe {
- sys::init(argc, argv);
+ sys::init(argc, argv, sigpipe);
let main_guard = sys::thread::guard::init();
// Next, set up the current Thread with the guard information we just
main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe),
argc: isize,
argv: *const *const u8,
+ sigpipe: u8,
) -> Result<isize, !> {
use crate::{mem, panic};
let rt_abort = move |e| {
// prevent libstd from accidentally introducing a panic to these functions. Another is from
// user code from `main` or, more nefariously, as described in e.g. issue #86030.
// SAFETY: Only called once during runtime initialization.
- panic::catch_unwind(move || unsafe { init(argc, argv) }).map_err(rt_abort)?;
+ panic::catch_unwind(move || unsafe { init(argc, argv, sigpipe) }).map_err(rt_abort)?;
let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize)
.map_err(move |e| {
mem::forget(e);
main: fn() -> T,
argc: isize,
argv: *const *const u8,
+ #[cfg(not(bootstrap))] sigpipe: u8,
) -> isize {
let Ok(v) = lang_start_internal(
&move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report().to_i32(),
argc,
argv,
+ #[cfg(bootstrap)]
+ 2, // Temporary inlining of sigpipe::DEFAULT until bootstrap stops being special
+ #[cfg(not(bootstrap))]
+ sigpipe,
);
v
}
use crate::marker::PhantomData;
use crate::mem::MaybeUninit;
use crate::panic::{RefUnwindSafe, UnwindSafe};
-use crate::pin::Pin;
use crate::sync::Once;
/// A synchronization primitive which can be written to only once.
Ok(unsafe { self.get_unchecked() })
}
- /// Internal-only API that gets the contents of the cell, initializing it
- /// in two steps with `f` and `g` if the cell was empty.
- ///
- /// `f` is called to construct the value, which is then moved into the cell
- /// and given as a (pinned) mutable reference to `g` to finish
- /// initialization.
- ///
- /// This allows `g` to inspect an manipulate the value after it has been
- /// moved into its final place in the cell, but before the cell is
- /// considered initialized.
- ///
- /// # Panics
- ///
- /// If `f` or `g` panics, the panic is propagated to the caller, and the
- /// cell remains uninitialized.
- ///
- /// With the current implementation, if `g` panics, the value from `f` will
- /// not be dropped. This should probably be fixed if this is ever used for
- /// a type where this matters.
- ///
- /// It is an error to reentrantly initialize the cell from `f`. The exact
- /// outcome is unspecified. Current implementation deadlocks, but this may
- /// be changed to a panic in the future.
- pub(crate) fn get_or_init_pin<F, G>(self: Pin<&Self>, f: F, g: G) -> Pin<&T>
- where
- F: FnOnce() -> T,
- G: FnOnce(Pin<&mut T>),
- {
- if let Some(value) = self.get_ref().get() {
- // SAFETY: The inner value was already initialized, and will not be
- // moved anymore.
- return unsafe { Pin::new_unchecked(value) };
- }
-
- let slot = &self.value;
-
- // Ignore poisoning from other threads
- // If another thread panics, then we'll be able to run our closure
- self.once.call_once_force(|_| {
- let value = f();
- // SAFETY: We use the Once (self.once) to guarantee unique access
- // to the UnsafeCell (slot).
- let value: &mut T = unsafe { (&mut *slot.get()).write(value) };
- // SAFETY: The value has been written to its final place in
- // self.value. We do not to move it anymore, which we promise here
- // with a Pin<&mut T>.
- g(unsafe { Pin::new_unchecked(value) });
- });
-
- // SAFETY: The inner value has been initialized, and will not be moved
- // anymore.
- unsafe { Pin::new_unchecked(self.get_ref().get_unchecked()) }
- }
-
/// Consumes the `OnceLock`, returning the wrapped value. Returns
/// `None` if the cell was empty.
///
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(argc: isize, argv: *const *const u8) {
+pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
let _ = net::init();
args::init(argc, argv);
}
Mutex { inner: Spinlock::new(MutexInner::new()) }
}
- #[inline]
- pub unsafe fn init(&mut self) {}
-
#[inline]
pub unsafe fn lock(&self) {
loop {
Mutex { mtx: SpinIdOnceCell::new() }
}
- pub unsafe fn init(&mut self) {
- // Initialize `self.mtx` eagerly
- let id = new_mtx().unwrap_or_else(|e| fail(e, &"acre_mtx"));
- unsafe { self.mtx.set_unchecked((id, ())) };
- }
-
/// Get the inner mutex's ID, which is lazily created.
fn raw(&self) -> abi::ID {
match self.mtx.get_or_try_init(|| new_mtx().map(|id| (id, ()))) {
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(argc: isize, argv: *const *const u8) {
+pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
unsafe {
args::init(argc, argv);
}
Mutex { inner: SpinMutex::new(WaitVariable::new(false)) }
}
- #[inline]
- pub unsafe fn init(&mut self) {}
-
#[inline]
pub unsafe fn lock(&self) {
let mut guard = self.inner.lock();
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
+pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
// SAFETY: must be called only once during runtime cleanup.
pub unsafe fn cleanup() {}
Mutex { futex: AtomicU32::new(UNLOCKED) }
}
- #[inline]
- pub unsafe fn init(&mut self) {}
-
#[inline]
pub unsafe fn try_lock(&self) -> bool {
let thread_self = zx_thread_self();
Self { futex: AtomicU32::new(0) }
}
- #[inline]
- pub unsafe fn init(&mut self) {}
-
#[inline]
pub unsafe fn try_lock(&self) -> bool {
self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_ok()
Mutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
}
#[inline]
- pub unsafe fn init(&mut self) {
+ unsafe fn init(&mut self) {
// Issue #33770
//
// A pthread mutex initialized with PTHREAD_MUTEX_INITIALIZER will have
pub mod time;
#[cfg(target_os = "espidf")]
-pub fn init(argc: isize, argv: *const *const u8) {}
+pub fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {}
#[cfg(not(target_os = "espidf"))]
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(argc: isize, argv: *const *const u8) {
+// See `fn init()` in `library/std/src/rt.rs` for docs on `sigpipe`.
+pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
// The standard streams might be closed on application startup. To prevent
// std::io::{stdin, stdout,stderr} objects from using other unrelated file
// resources opened later, we reopen standards streams when they are closed.
// want!
//
// Hence, we set SIGPIPE to ignore when the program starts up in order
- // to prevent this problem.
- reset_sigpipe();
+ // to prevent this problem. Add `#[unix_sigpipe = "..."]` above `fn main()` to
+ // alter this behavior.
+ reset_sigpipe(sigpipe);
stack_overflow::init();
args::init(argc, argv);
}
}
- unsafe fn reset_sigpipe() {
+ unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) {
#[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))]
- rtassert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
+ {
+ // We don't want to add this as a public type to libstd, nor do we
+ // want to `include!` a file from the compiler (which would break
+ // Miri and xargo for example), so we choose to duplicate these
+ // constants from `compiler/rustc_session/src/config/sigpipe.rs`.
+ // See the other file for docs. NOTE: Make sure to keep them in
+ // sync!
+ mod sigpipe {
+ pub const INHERIT: u8 = 1;
+ pub const SIG_IGN: u8 = 2;
+ pub const SIG_DFL: u8 = 3;
+ }
+
+ let handler = match sigpipe {
+ sigpipe::INHERIT => None,
+ sigpipe::SIG_IGN => Some(libc::SIG_IGN),
+ sigpipe::SIG_DFL => Some(libc::SIG_DFL),
+ _ => unreachable!(),
+ };
+ if let Some(handler) = handler {
+ rtassert!(signal(libc::SIGPIPE, handler) != libc::SIG_ERR);
+ }
+ }
}
}
Some(b"") => Cgroup::V2,
Some(controllers)
if from_utf8(controllers)
- .is_ok_and(|c| c.split(",").any(|c| c == "cpu")) =>
+ .is_ok_and(|c| c.split(',').any(|c| c == "cpu")) =>
{
Cgroup::V1
}
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
+pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
// SAFETY: must be called only once during runtime cleanup.
// NOTE: this is not guaranteed to run, for example when the program aborts.
Mutex { locked: Cell::new(false) }
}
- #[inline]
- pub unsafe fn init(&mut self) {}
-
#[inline]
pub unsafe fn lock(&self) {
assert_eq!(self.locked.replace(true), false, "cannot recursively acquire mutex");
status >= 0
}
-pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002;
+pub const BCRYPT_RNG_ALG_HANDLE: usize = 0x81;
#[repr(C)]
pub struct UNICODE_STRING {
MaximumFileInfoByHandlesClass,
}
+#[repr(C)]
+pub struct FILE_ATTRIBUTE_TAG_INFO {
+ pub FileAttributes: DWORD,
+ pub ReparseTag: DWORD,
+}
+
#[repr(C)]
pub struct FILE_DISPOSITION_INFO {
pub DeleteFile: BOOLEAN,
cvt(c::GetFileInformationByHandle(self.handle.as_raw_handle(), &mut info))?;
let mut reparse_tag = 0;
if info.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
- let mut b =
- Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
- if let Ok((_, buf)) = self.reparse_point(&mut b) {
- reparse_tag = (*buf).ReparseTag;
+ let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed();
+ cvt(c::GetFileInformationByHandleEx(
+ self.handle.as_raw_handle(),
+ c::FileAttributeTagInfo,
+ ptr::addr_of_mut!(attr_tag).cast(),
+ mem::size_of::<c::FILE_ATTRIBUTE_TAG_INFO>().try_into().unwrap(),
+ ))?;
+ if attr_tag.FileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
+ reparse_tag = attr_tag.ReparseTag;
}
}
Ok(FileAttr {
attr.file_size = info.AllocationSize as u64;
attr.number_of_links = Some(info.NumberOfLinks);
if attr.file_type().is_reparse_point() {
- let mut b =
- Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
- if let Ok((_, buf)) = self.reparse_point(&mut b) {
- attr.reparse_tag = (*buf).ReparseTag;
+ let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed();
+ cvt(c::GetFileInformationByHandleEx(
+ self.handle.as_raw_handle(),
+ c::FileAttributeTagInfo,
+ ptr::addr_of_mut!(attr_tag).cast(),
+ mem::size_of::<c::FILE_ATTRIBUTE_TAG_INFO>().try_into().unwrap(),
+ ))?;
+ if attr_tag.FileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
+ reparse_tag = attr_tag.ReparseTag;
}
}
Ok(attr)
pub const fn new() -> Mutex {
Mutex { srwlock: UnsafeCell::new(c::SRWLOCK_INIT) }
}
- #[inline]
- pub unsafe fn init(&mut self) {}
#[inline]
pub unsafe fn lock(&self) {
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
+pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {
stack_overflow::init();
// Normally, `thread::spawn` will call `Thread::set_name` but since this thread already
+//! # Random key generation
+//!
+//! This module wraps the RNG provided by the OS. There are a few different
+//! ways to interface with the OS RNG so it's worth exploring each of the options.
+//! Note that at the time of writing these all go through the (undocumented)
+//! `bcryptPrimitives.dll` but they use different route to get there.
+//!
+//! Originally we were using [`RtlGenRandom`], however that function is
+//! deprecated and warns it "may be altered or unavailable in subsequent versions".
+//!
+//! So we switched to [`BCryptGenRandom`] with the `BCRYPT_USE_SYSTEM_PREFERRED_RNG`
+//! flag to query and find the system configured RNG. However, this change caused a small
+//! but significant number of users to experience panics caused by a failure of
+//! this function. See [#94098].
+//!
+//! The current version changes this to use the `BCRYPT_RNG_ALG_HANDLE`
+//! [Pseudo-handle], which gets the default RNG algorithm without querying the
+//! system preference thus hopefully avoiding the previous issue.
+//! This is only supported on Windows 10+ so a fallback is used for older versions.
+//!
+//! [#94098]: https://github.com/rust-lang/rust/issues/94098
+//! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
+//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
+//! [Pseudo-handle]: https://docs.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-pseudo-handles
use crate::io;
use crate::mem;
use crate::ptr;
use crate::sys::c;
+/// Generates high quality secure random keys for use by [`HashMap`].
+///
+/// This is used to seed the default [`RandomState`].
+///
+/// [`HashMap`]: crate::collections::HashMap
+/// [`RandomState`]: crate::collections::hash_map::RandomState
pub fn hashmap_random_keys() -> (u64, u64) {
let mut v = (0, 0);
let ret = unsafe {
+ let size = mem::size_of_val(&v).try_into().unwrap();
c::BCryptGenRandom(
- ptr::null_mut(),
- &mut v as *mut _ as *mut u8,
- mem::size_of_val(&v) as c::ULONG,
- c::BCRYPT_USE_SYSTEM_PREFERRED_RNG,
+ // BCRYPT_RNG_ALG_HANDLE is only supported in Windows 10+.
+ // So for Windows 8.1 and Windows 7 we'll need a fallback when this fails.
+ ptr::invalid_mut(c::BCRYPT_RNG_ALG_HANDLE),
+ ptr::addr_of_mut!(v).cast(),
+ size,
+ 0,
)
};
if ret != 0 { fallback_rng() } else { v }
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;
+use super::mutex as sys;
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
///
/// synchronization is left to the mutex, making relaxed memory ordering for
/// the `owner` field fine in all cases.
pub struct ReentrantMutex<T> {
- mutex: sys::Mutex,
+ mutex: sys::MovableMutex,
owner: AtomicUsize,
lock_count: UnsafeCell<u32>,
data: T,
- _pinned: PhantomPinned,
}
unsafe impl<T: Send> Send for ReentrantMutex<T> {}
/// guarded data.
#[must_use = "if unused the ReentrantMutex will immediately unlock"]
pub struct ReentrantMutexGuard<'a, T: 'a> {
- lock: Pin<&'a ReentrantMutex<T>>,
+ lock: &'a ReentrantMutex<T>,
}
impl<T> !Send for ReentrantMutexGuard<'_, T> {}
impl<T> ReentrantMutex<T> {
/// Creates a new reentrant mutex in an unlocked state.
- ///
- /// # Unsafety
- ///
- /// This function is unsafe because it is required that `init` is called
- /// once this mutex is in its final resting place, and only then are the
- /// lock/unlock methods safe.
- pub const unsafe fn new(t: T) -> ReentrantMutex<T> {
+ pub const fn new(t: T) -> ReentrantMutex<T> {
ReentrantMutex {
- mutex: sys::Mutex::new(),
+ mutex: sys::MovableMutex::new(),
owner: AtomicUsize::new(0),
lock_count: UnsafeCell::new(0),
data: t,
- _pinned: PhantomPinned,
}
}
- /// Initializes this mutex so it's ready for use.
- ///
- /// # Unsafety
- ///
- /// 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().mutex.init()
- }
-
/// Acquires a mutex, blocking the current thread until it is able to do so.
///
/// This function will block the caller until it is available to acquire the mutex.
/// If another user of this mutex panicked while holding the mutex, then
/// this call will return failure if the mutex would otherwise be
/// acquired.
- pub fn lock(self: Pin<&Self>) -> ReentrantMutexGuard<'_, T> {
+ pub fn lock(&self) -> ReentrantMutexGuard<'_, T> {
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.
+ // Safety: We only touch lock_count when we own the lock.
unsafe {
if self.owner.load(Relaxed) == this_thread {
self.increment_lock_count();
} else {
- self.mutex.lock();
+ self.mutex.raw_lock();
self.owner.store(this_thread, Relaxed);
debug_assert_eq!(*self.lock_count.get(), 0);
*self.lock_count.get() = 1;
/// If another user of this mutex panicked while holding the mutex, then
/// this call will return failure if the mutex would otherwise be
/// acquired.
- pub fn try_lock(self: Pin<&Self>) -> Option<ReentrantMutexGuard<'_, T>> {
+ pub fn try_lock(&self) -> Option<ReentrantMutexGuard<'_, T>> {
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.
+ // Safety: We only touch lock_count when we own the lock.
unsafe {
if self.owner.load(Relaxed) == this_thread {
self.increment_lock_count();
impl<T> Drop for ReentrantMutexGuard<'_, T> {
#[inline]
fn drop(&mut self) {
- // Safety: We own the lock, and the lock is pinned.
+ // Safety: We own the lock.
unsafe {
*self.lock.lock_count.get() -= 1;
if *self.lock.lock_count.get() == 0 {
self.lock.owner.store(0, Relaxed);
- self.lock.mutex.unlock();
+ self.lock.mutex.raw_unlock();
}
}
}
-use crate::boxed::Box;
use crate::cell::RefCell;
-use crate::pin::Pin;
use crate::sync::Arc;
use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
use crate::thread;
#[test]
fn smoke() {
- let m = unsafe {
- let mut m = Box::pin(ReentrantMutex::new(()));
- m.as_mut().init();
- m
- };
- let m = m.as_ref();
+ let m = ReentrantMutex::new(());
{
let a = m.lock();
{
#[test]
fn is_mutex() {
- let m = unsafe {
- // FIXME: Simplify this if Arc gets an Arc::get_pin_mut.
- let mut m = Arc::new(ReentrantMutex::new(RefCell::new(0)));
- Pin::new_unchecked(Arc::get_mut_unchecked(&mut m)).init();
- Pin::new_unchecked(m)
- };
+ let m = Arc::new(ReentrantMutex::new(RefCell::new(0)));
let m2 = m.clone();
- let lock = m.as_ref().lock();
+ let lock = m.lock();
let child = thread::spawn(move || {
- let lock = m2.as_ref().lock();
+ let lock = m2.lock();
assert_eq!(*lock.borrow(), 4950);
});
for i in 0..100 {
- let lock = m.as_ref().lock();
+ let lock = m.lock();
*lock.borrow_mut() += i;
}
drop(lock);
#[test]
fn trylock_works() {
- let m = unsafe {
- // FIXME: Simplify this if Arc gets an Arc::get_pin_mut.
- let mut m = Arc::new(ReentrantMutex::new(()));
- Pin::new_unchecked(Arc::get_mut_unchecked(&mut m)).init();
- Pin::new_unchecked(m)
- };
+ let m = Arc::new(ReentrantMutex::new(()));
let m2 = m.clone();
- let _lock = m.as_ref().try_lock();
- let _lock2 = m.as_ref().try_lock();
+ let _lock = m.try_lock();
+ let _lock2 = m.try_lock();
thread::spawn(move || {
- let lock = m2.as_ref().try_lock();
+ let lock = m2.try_lock();
assert!(lock.is_none());
})
.join()
.unwrap();
- let _lock3 = m.as_ref().try_lock();
+ let _lock3 = m.try_lock();
}
pub struct Answer<'a>(pub ReentrantMutexGuard<'a, RefCell<u32>>);
compiler: build_compiler,
target: target_compiler.host,
});
- builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe("ld", target_compiler.host)));
+ for name in crate::LLD_FILE_NAMES {
+ builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe(name, target_compiler.host)));
+ }
}
if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
let gcc_lld_src_dir = src_dir.join("gcc-ld");
let gcc_lld_dst_dir = dst_dir.join("gcc-ld");
t!(fs::create_dir(&gcc_lld_dst_dir));
- let exe_name = exe("ld", compiler.host);
- builder.copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name));
+ for name in crate::LLD_FILE_NAMES {
+ let exe_name = exe(name, compiler.host);
+ builder
+ .copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name));
+ }
}
// Man pages
"opt", // used to optimize LLVM bytecode
];
+/// LLD file names for all flavors.
+const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"];
+
pub const VERSION: usize = 2;
/// Extra --check-cfg to add when building
python3 ../x.py test --stage 0 src/tools/compiletest && \
python3 ../x.py test --stage 2 src/tools/tidy && \
python3 ../x.py test --stage 0 core alloc std test proc_macro && \
- python3 ../x.py doc --stage 0 library/test && \
+ # Build both public and internal documentation.
+ RUSTDOCFLAGS="--document-private-items" python3 ../x.py doc --stage 0 library/test && \
/scripts/validate-toolstate.sh && \
/scripts/validate-error-codes.sh && \
reuse lint && \
The `package` file describes our package's name and version number. Every
package must contain one.
-**`pkg/hello_fuchsia.manifest`**
+**`pkg/hello_fuchsia.manifest` if using cargo**
```txt
-bin/hello_fuchsia=target/x86_64-fuchsia/debug/hello_fuchsia # If using cargo...
-bin/hello_fuchsia=bin/hello_fuchsia # If using rustc...
+bin/hello_fuchsia=target/x86_64-fuchsia/debug/hello_fuchsia
+lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
+lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
+meta/package=pkg/meta/package
+meta/hello_fuchsia.cm=pkg/meta/hello_fuchsia.cm
+```
+
+**`pkg/hello_fuchsia.manifest` if using rustc**
+```txt
+bin/hello_fuchsia=bin/hello_fuchsia
lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
meta/package=pkg/meta/package
```sh
${SDK_PATH}/tools/${ARCH}/ffx component run \
+ /core/ffx-laboratory:hello_fuchsia \
fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
```
```sh
${SDK_PATH}/tools/${ARCH}/ffx component run \
--recreate \
+ /core/ffx-laboratory:hello_fuchsia \
fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
```
--- /dev/null
+# `unix_sigpipe`
+
+The tracking issue for this feature is: [#97889]
+
+[#97889]: https://github.com/rust-lang/rust/issues/97889
+
+---
+
+The `#[unix_sigpipe = "..."]` attribute on `fn main()` can be used to specify how libstd shall setup `SIGPIPE` on Unix platforms before invoking `fn main()`. This attribute is ignored on non-Unix targets. There are three variants:
+* `#[unix_sigpipe = "inherit"]`
+* `#[unix_sigpipe = "sig_dfl"]`
+* `#[unix_sigpipe = "sig_ign"]`
+
+## `#[unix_sigpipe = "inherit"]`
+
+Leave `SIGPIPE` untouched before entering `fn main()`. Unless the parent process has changed the default `SIGPIPE` handler from `SIG_DFL` to something else, this will behave the same as `#[unix_sigpipe = "sig_dfl"]`.
+
+## `#[unix_sigpipe = "sig_dfl"]`
+
+Set the `SIGPIPE` handler to `SIG_DFL`. This will result in your program getting killed if it tries to write to a closed pipe. This is normally what you want if your program produces textual output.
+
+### Example
+
+```rust,no_run
+#![feature(unix_sigpipe)]
+#[unix_sigpipe = "sig_dfl"]
+fn main() { loop { println!("hello world"); } }
+```
+
+```bash
+% ./main | head -n 1
+hello world
+```
+
+## `#[unix_sigpipe = "sig_ign"]`
+
+Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers.
+
+This is what libstd has done by default since 2014. Omitting `#[unix_sigpipe = "..."]` is the same as having `#[unix_sigpipe = "sig_ign"]`.
+
+### Example
+
+```rust,no_run
+#![feature(unix_sigpipe)]
+#[unix_sigpipe = "sig_ign"]
+fn main() { loop { println!("hello world"); } }
+```
+
+```bash
+% ./main | head -n 1
+hello world
+thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', library/std/src/io/stdio.rs:1016:9
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+```
pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item {
let kind = match variant.ctor_kind {
- CtorKind::Const => Variant::CLike,
+ CtorKind::Const => Variant::CLike(match variant.discr {
+ ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }),
+ ty::VariantDiscr::Relative(_) => None,
+ }),
CtorKind::Fn => Variant::Tuple(
variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
),
fn clean_variant_data<'tcx>(
variant: &hir::VariantData<'tcx>,
+ disr_expr: &Option<hir::AnonConst>,
cx: &mut DocContext<'tcx>,
) -> Variant {
match variant {
hir::VariantData::Tuple(..) => {
Variant::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect())
}
- hir::VariantData::Unit(..) => Variant::CLike,
+ hir::VariantData::Unit(..) => Variant::CLike(disr_expr.map(|disr| Discriminant {
+ expr: Some(disr.body),
+ value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(),
+ })),
}
}
}
fn clean_variant<'tcx>(variant: &hir::Variant<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
- let kind = VariantItem(clean_variant_data(&variant.data, cx));
+ let kind = VariantItem(clean_variant_data(&variant.data, &variant.disr_expr, cx));
let what_rustc_thinks =
Item::from_hir_id_and_parts(variant.id, Some(variant.ident.name), kind, cx);
// don't show `pub` for variants, which are always public
#[derive(Clone, Debug)]
pub(crate) enum Variant {
- CLike,
+ CLike(Option<Discriminant>),
Tuple(Vec<Item>),
Struct(VariantStruct),
}
pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
match *self {
Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()),
- Self::CLike | Self::Tuple(_) => None,
+ Self::CLike(..) | Self::Tuple(_) => None,
}
}
}
+#[derive(Clone, Debug)]
+pub(crate) struct Discriminant {
+ // In the case of cross crate re-exports, we don't have the nessesary information
+ // to reconstruct the expression of the discriminant, only the value.
+ pub(super) expr: Option<BodyId>,
+ pub(super) value: DefId,
+}
+
+impl Discriminant {
+ /// Will be `None` in the case of cross-crate reexports, and may be
+ /// simplified
+ pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
+ self.expr.map(|body| print_const_expr(tcx, body))
+ }
+ /// Will always be a machine readable number, without underscores or suffixes.
+ pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> String {
+ print_evaluated_const(tcx, self.value, false).unwrap()
+ }
+}
+
/// Small wrapper around [`rustc_span::Span`] that adds helper methods
/// and enforces calling [`rustc_span::Span::source_callsite()`].
#[derive(Copy, Clone, Debug)]
match *self {
ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
- print_evaluated_const(tcx, def_id)
+ print_evaluated_const(tcx, def_id, true)
}
}
}
}
}
-pub(crate) fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<String> {
+pub(crate) fn print_evaluated_const(
+ tcx: TyCtxt<'_>,
+ def_id: DefId,
+ underscores_and_type: bool,
+) -> Option<String> {
tcx.const_eval_poly(def_id).ok().and_then(|val| {
let ty = tcx.type_of(def_id);
match (val, ty.kind()) {
(ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
(ConstValue::Scalar(_), _) => {
let const_ = mir::ConstantKind::from_value(val, ty);
- Some(print_const_with_custom_print_scalar(tcx, const_))
+ Some(print_const_with_custom_print_scalar(tcx, const_, underscores_and_type))
}
_ => None,
}
.collect()
}
-fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: mir::ConstantKind<'_>) -> String {
+fn print_const_with_custom_print_scalar(
+ tcx: TyCtxt<'_>,
+ ct: mir::ConstantKind<'_>,
+ underscores_and_type: bool,
+) -> String {
// Use a slightly different format for integer types which always shows the actual value.
// For all other types, fallback to the original `pretty_print_const`.
match (ct, ct.ty().kind()) {
(mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Uint(ui)) => {
- format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
+ if underscores_and_type {
+ format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
+ } else {
+ int.to_string()
+ }
}
(mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Int(i)) => {
let ty = tcx.lift(ct.ty()).unwrap();
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
let data = int.assert_bits(size);
let sign_extended_data = size.sign_extend(data) as i128;
- format!(
- "{}{}",
- format_integer_with_underscore_sep(&sign_extended_data.to_string()),
- i.name_str()
- )
+ if underscores_and_type {
+ format!(
+ "{}{}",
+ format_integer_with_underscore_sep(&sign_extended_data.to_string()),
+ i.name_str()
+ )
+ } else {
+ sign_extended_data.to_string()
+ }
}
_ => ct.to_string(),
}
let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
VariantItem(Variant::Tuple(fields))
}
- Variant::CLike => VariantItem(Variant::CLike),
+ Variant::CLike(disr) => VariantItem(Variant::CLike(disr)),
},
ExternCrateItem { src: _ }
| ImportItem(_)
let Some(v) = shared.cache.impls.get(&def_id) else { return (Vec::new(), Vec::new(), Vec::new()) };
// Since there is no "direct implementation" on the reference primitive type, we filter out
// every implementation which isn't a trait implementation.
- let traits: Vec<_> = v.iter().filter(|i| i.inner_impl().trait_.is_some()).collect();
+ let traits = v.iter().filter(|i| i.inner_impl().trait_.is_some());
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
- traits.into_iter().partition(|t| t.inner_impl().kind.is_auto());
+ traits.partition(|t| t.inner_impl().kind.is_auto());
let (blanket_impl, concrete): (Vec<&Impl>, _) =
concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
let name = v.name.unwrap();
match *v.kind {
clean::VariantItem(ref var) => match var {
- clean::Variant::CLike => write!(w, "{}", name),
+ // FIXME(#101337): Show discriminant
+ clean::Variant::CLike(..) => write!(w, "{}", name),
clean::Variant::Tuple(ref s) => {
write!(w, "{}(", name);
print_tuple_struct_fields(w, cx, s);
fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'tcx>) {
if let ExprKind::MethodCall(segment, ..) = expr.kind {
- if let Some(hir_id) = segment.hir_id {
- let hir = self.tcx.hir();
- let body_id = hir.enclosing_body_owner(hir_id);
- // FIXME: this is showing error messages for parts of the code that are not
- // compiled (because of cfg)!
- //
- // See discussion in https://github.com/rust-lang/rust/issues/69426#issuecomment-1019412352
- let typeck_results = self.tcx.typeck_body(
- hir.maybe_body_owned_by(body_id).expect("a body which isn't a body"),
+ let hir = self.tcx.hir();
+ let body_id = hir.enclosing_body_owner(segment.hir_id);
+ // FIXME: this is showing error messages for parts of the code that are not
+ // compiled (because of cfg)!
+ //
+ // See discussion in https://github.com/rust-lang/rust/issues/69426#issuecomment-1019412352
+ let typeck_results = self
+ .tcx
+ .typeck_body(hir.maybe_body_owned_by(body_id).expect("a body which isn't a body"));
+ if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
+ self.matches.insert(
+ segment.ident.span,
+ match hir.span_if_local(def_id) {
+ Some(span) => LinkFromSrc::Local(clean::Span::new(span)),
+ None => LinkFromSrc::External(def_id),
+ },
);
- if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
- self.matches.insert(
- segment.ident.span,
- match hir.span_if_local(def_id) {
- Some(span) => LinkFromSrc::Local(clean::Span::new(span)),
- None => LinkFromSrc::External(def_id),
- },
- );
- }
}
} else if self.handle_macro(expr.span) {
// We don't want to go deeper into the macro.
if line.starts_with(&prefix) {
continue;
}
- if line.ends_with(",") {
+ if line.ends_with(',') {
ret.push(line[..line.len() - 1].to_string());
} else {
// No comma (it's the case for the last added crate line)
margin-bottom: .6em;
}
-.content .impl-items > .item-info {
- margin-left: 40px;
-}
-
-.methods > .item-info, .content .impl-items > .item-info {
- margin-top: -8px;
-}
-
-.impl-items {
- flex-basis: 100%;
-}
-
#main-content > .item-info {
margin-top: 0;
margin-left: 0;
width: 100%;
background-color: var(--button-background-color);
}
+.search-input:focus {
+ border-color: var(--search-input-focused-border-color);
+}
.search-results {
display: none;
float: right;
}
+.rightside:not(a),
+.out-of-band {
+ color: var(--right-side-color);
+}
+
+
.impl-items .srclink, .impl .srclink, .methods .srclink {
/* Override header settings otherwise it's too bold */
font-weight: normal;
.code-attribute {
font-weight: 300;
+ color: var(--code-attribute-color);
}
.item-spacer {
margin-left: 24px;
}
-.toggle-label {
- display: inline-block;
- margin-left: 4px;
- margin-top: 3px;
-}
-
:target > code, :target > .code-header {
opacity: 1;
}
background-color: var(--button-background-color);
}
+#copy-path {
+ color: var(--copy-path-button-color);
+}
+#copy-path > img {
+ filter: var(--copy-path-img-filter);
+}
+#copy-path:hover > img {
+ filter: var(--copy-path-img-hover-filter);
+}
+
@keyframes rotating {
from {
transform: rotate(0deg);
opacity: .5;
}
+details.rustdoc-toggle > summary.hideme > span,
+details.rustdoc-toggle > summary::before,
+.more-examples-toggle summary, .more-examples-toggle .hide-more {
+ color: var(--toggles-color);
+}
+
/* Screen readers see the text version at the end the line.
Visual readers see the icon at the start of the line, but small and transparent. */
details.rustdoc-toggle > summary::after {
background-color: var(--sidebar-background-color);
}
- .source nav:not(.sidebar).sub {
- margin-left: 32px;
- }
-
.content {
margin-left: 0px;
}
#main-content > div > details.rustdoc-toggle > summary::before {
left: -11px;
}
+
+ /* Align summary-nested and unnested item-info gizmos. */
+ .content .impl-items > .item-info {
+ margin-left: 34px;
+ }
}
@media print {
--headings-border-bottom-color: #5c6773;
--border-color: #5c6773;
--button-background-color: #141920;
+ --right-side-color: grey;
+ --code-attribute-color: #999;
+ --toggles-color: #999;
+ --search-input-focused-border-color: #5c6773; /* Same as `--border-color`. */
+ --copy-path-button-color: #fff;
+ --copy-path-img-filter: invert(70%);
+ --copy-path-img-hover-filter: invert(100%);
}
.slider {
background: #333;
}
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before {
- color: #999;
-}
-
details.rustdoc-toggle > summary::before {
filter: invert(100%);
}
background: none;
}
-.rightside:not(a),
-.out-of-band {
- color: grey;
-}
-
.result-name .primitive > i, .result-name .keyword > i {
color: #788797;
}
color: #c5c5c5;
}
-.toggle-label,
-.code-attribute {
- color: #999;
-}
-
:target {
background: rgba(255, 236, 164, 0.06);
border-right: 3px solid rgba(255, 180, 76, 0.85);
/* FIXME: these rules should be at the bottom of the file but currently must be
above the `@media (max-width: 700px)` rules due to a bug in the css checker */
/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
-.search-input:focus {}
.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,
.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro {}
.content span.struct,.content a.struct,.block a.current.struct {}
filter: invert(100);
}
-#copy-path {
- color: #fff;
-}
-#copy-path > img {
- filter: invert(70%);
-}
-#copy-path:hover > img {
- filter: invert(100%);
-}
-
#settings-menu > a:hover, #settings-menu > a:focus,
#help-button > button:hover, #help-button > button:focus {
border-color: #e0e0e0;
border-color: white;
color: white;
}
-.more-examples-toggle summary, .more-examples-toggle .hide-more {
- color: #999;
-}
.scraped-example .example-wrap .rust span.highlight {
background: rgb(91, 59, 1);
}
--headings-border-bottom-color: #d2d2d2;
--border-color: #e0e0e0;
--button-background-color: #f0f0f0;
+ --right-side-color: grey;
+ --code-attribute-color: #999;
+ --toggles-color: #999;
+ --search-input-focused-border-color: #008dfd;
+ --copy-path-button-color: #999;
+ --copy-path-img-filter: invert(50%);
+ --copy-path-img-hover-filter: invert(65%);
}
.slider {
background: #333;
}
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before {
- color: #999;
-}
-
details.rustdoc-toggle > summary::before {
filter: invert(100%);
}
.search-input {
color: #111;
- border-color: #f0f0f0;
}
#crate-search-div::after {
filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);
}
-.search-input:focus {
- border-color: #008dfd;
-}
-
.stab { background: #314559; }
.stab.portability > code {
background: none;
}
-.rightside:not(a),
-.out-of-band {
- color: grey;
-}
-
.line-numbers :target { background-color: transparent; }
/* Code highlighting */
background-color: #4e8bca;
}
-.toggle-label,
-.code-attribute {
- color: #999;
-}
-
:target {
background-color: #494a3d;
border-right: 3px solid #bb7410;
border-color: #ffb900;
}
-#copy-path {
- color: #999;
-}
-#copy-path > img {
- filter: invert(50%);
-}
-#copy-path:hover > img {
- filter: invert(65%);
-}
-
.search-results .result-name span.alias {
color: #fff;
}
border-color: white;
color: white;
}
-.more-examples-toggle summary, .more-examples-toggle .hide-more {
- color: #999;
-}
.scraped-example .example-wrap .rust span.highlight {
background: rgb(91, 59, 1);
}
--headings-border-bottom-color: #ddd;
--border-color: #e0e0e0;
--button-background-color: #fff;
+ --right-side-color: grey;
+ --code-attribute-color: #999;
+ --toggles-color: #999;
+ --search-input-focused-border-color: #66afe9;
+ --copy-path-button-color: #999;
+ --copy-path-img-filter: invert(50%);
+ --copy-path-img-hover-filter: invert(35%);
}
.slider {
background: #eee;
}
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before {
- color: #999;
-}
-
#crate-search-div::after {
/* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */
filter: invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);
filter: invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);
}
-.search-input:focus {
- border-color: #66afe9;
-}
-
.stab { background: #FFF5D6; border-color: #FFC600; }
.stab.portability > code { background: none; }
-.rightside:not(a),
-.out-of-band {
- color: grey;
-}
-
.line-numbers :target { background-color: transparent; }
/* Code highlighting */
background-color: #4e8bca;
}
-.toggle-label,
-.code-attribute {
- color: #999;
-}
-
:target {
background: #FDFFD3;
border-right: 3px solid #AD7C37;
border-color: #717171;
}
-#copy-path {
- color: #999;
-}
-#copy-path > img {
- filter: invert(50%);
-}
-#copy-path:hover > img {
- filter: invert(35%);
-}
-
.search-results .result-name span.alias {
color: #000;
}
border-color: black;
color: black;
}
-.more-examples-toggle summary, .more-examples-toggle .hide-more {
- color: #999;
-}
.scraped-example .example-wrap .rust span.highlight {
background: #fcffd6;
}
},
QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath {
name: assoc.name.to_string(),
- args: Box::new(assoc.args.clone().into_tcx(tcx)),
+ args: Box::new(assoc.args.into_tcx(tcx)),
self_type: Box::new(self_type.into_tcx(tcx)),
trait_: trait_.into_tcx(tcx),
},
fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
use clean::Variant::*;
match variant {
- CLike => Variant::Plain,
+ CLike(disr) => Variant::Plain(disr.map(|disr| disr.into_tcx(tcx))),
Tuple(fields) => Variant::Tuple(
fields
.into_iter()
}
}
+impl FromWithTcx<clean::Discriminant> for Discriminant {
+ fn from_tcx(disr: clean::Discriminant, tcx: TyCtxt<'_>) -> Self {
+ Discriminant {
+ // expr is only none if going throught the inlineing path, which gets
+ // `rustc_middle` types, not `rustc_hir`, but because JSON never inlines
+ // the expr is always some.
+ expr: disr.expr(tcx).unwrap(),
+ value: disr.value(tcx),
+ }
+ }
+}
+
impl FromWithTcx<clean::Import> for Import {
fn from_tcx(import: clean::Import, tcx: TyCtxt<'_>) -> Self {
use clean::ImportKind::*;
return;
}
}
- hir::ExprKind::MethodCall(path, _, call_span) => {
+ hir::ExprKind::MethodCall(path, _, _, call_span) => {
let types = tcx.typeck(ex.hir_id.owner);
let Some(def_id) = types.type_dependent_def_id(ex.hir_id) else {
trace!("type_dependent_def_id({}) = None", ex.hir_id);
VariantItem(i) => match i {
Variant::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)),
Variant::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)),
- Variant::CLike => {}
+ Variant::CLike(_) => {}
},
ExternCrateItem { src: _ }
| ImportItem(_)
-Subproject commit e3be3f64ecac101d14ceda759ba078ad0aaf3747
+Subproject commit 670e5f673acb736acbfce65e0ffe2c8cd115b93f
use serde::{Deserialize, Serialize};
/// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 18;
+pub const FORMAT_VERSION: u32 = 19;
/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
/// about the language items in the local crate, as well as info about external items to allow
#[serde(rename_all = "snake_case")]
#[serde(tag = "variant_kind", content = "variant_inner")]
pub enum Variant {
- Plain,
+ Plain(Option<Discriminant>),
Tuple(Vec<Type>),
Struct(Vec<Id>),
}
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub struct Discriminant {
+ /// The expression that produced the discriminant.
+ ///
+ /// Unlike `value`, this preserves the original formatting (eg suffixes,
+ /// hexadecimal, and underscores), making it unsuitable to be machine
+ /// interpreted.
+ ///
+ /// In some cases, when the value is to complex, this may be `"{ _ }"`.
+ /// When this occurs is unstable, and may change without notice.
+ pub expr: String,
+ /// The numerical value of the discriminant. Stored as a string due to
+ /// JSON's poor support for large integers, and the fact that it would need
+ /// to store from [`i128::MIN`] to [`u128::MAX`].
+ pub value: String,
+}
+
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum StructType {
use std::convert::TryFrom;
<[T; N.get()]>::try_from(())
//~^ error: the trait bound
+ //~| error: the trait bound
//~| error: mismatched types
}
--- /dev/null
+// This test ensures that the "item-info" looks about the same
+// whether or not it's inside a toggle.
+goto: file://|DOC_PATH|/lib2/struct.ItemInfoAlignmentTest.html
+
+// First, we try it in "desktop" mode.
+size: (1200, 870)
+compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ("x"))
+// Next, we try it in "mobile" mode (max-width: 700px).
+size: (650, 650)
+compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ("x"))
assert-css: (
".search-input",
{
- "border-color": "rgb(240, 240, 240)",
+ "border-color": "rgb(224, 224, 224)",
"background-color": "rgb(240, 240, 240)",
"color": "rgb(17, 17, 17)",
},
+++ /dev/null
-// Ensures that the search input border color changes on focus.
-goto: file://|DOC_PATH|/test_docs/index.html
-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
-reload:
-
-assert-css: (".search-input", {"border-color": "rgb(240, 240, 240)"})
-click: ".search-input"
-assert-css: (".search-input", {"border-color": "rgb(0, 141, 253)"})
-
-local-storage: {"rustdoc-theme": "light"}
-reload:
-
-assert-css: (".search-input", {"border-color": "rgb(224, 224, 224)"})
-click: ".search-input"
-assert-css: (".search-input", {"border-color": "rgb(102, 175, 233)"})
-
-local-storage: {"rustdoc-theme": "ayu"}
-reload:
-
-assert-css: (".search-input", {"border-color": "rgb(92, 103, 115)"})
-click: ".search-input"
-assert-css: (".search-input", {"border-color": "rgb(92, 103, 115)"})
type Output;
fn index(&self, index: Idx) -> &Self::Output;
}
+
+pub struct ItemInfoAlignmentTest;
+
+impl ItemInfoAlignmentTest {
+ /// This method has docs
+ #[deprecated]
+ pub fn foo() {}
+ #[deprecated]
+ pub fn bar() {}
+}
--- /dev/null
+#[repr(i8)]
+pub enum Ordering {
+ // @is "$.index[*][?(@.name=='Less')].inner.variant_inner.expr" '"-1"'
+ // @is "$.index[*][?(@.name=='Less')].inner.variant_inner.value" '"-1"'
+ Less = -1,
+ // @is "$.index[*][?(@.name=='Equal')].inner.variant_inner.expr" '"0"'
+ // @is "$.index[*][?(@.name=='Equal')].inner.variant_inner.value" '"0"'
+ Equal = 0,
+ // @is "$.index[*][?(@.name=='Greater')].inner.variant_inner.expr" '"1"'
+ // @is "$.index[*][?(@.name=='Greater')].inner.variant_inner.value" '"1"'
+ Greater = 1,
+}
--- /dev/null
+pub enum Foo {
+ // @is "$.index[*][?(@.name=='Addition')].inner.variant_inner.value" '"0"'
+ // @is "$.index[*][?(@.name=='Addition')].inner.variant_inner.expr" '"{ _ }"'
+ Addition = 0 + 0,
+ // @is "$.index[*][?(@.name=='Bin')].inner.variant_inner.value" '"1"'
+ // @is "$.index[*][?(@.name=='Bin')].inner.variant_inner.expr" '"0b1"'
+ Bin = 0b1,
+ // @is "$.index[*][?(@.name=='Oct')].inner.variant_inner.value" '"2"'
+ // @is "$.index[*][?(@.name=='Oct')].inner.variant_inner.expr" '"0o2"'
+ Oct = 0o2,
+ // @is "$.index[*][?(@.name=='PubConst')].inner.variant_inner.value" '"3"'
+ // @is "$.index[*][?(@.name=='PubConst')].inner.variant_inner.expr" '"THREE"'
+ PubConst = THREE,
+ // @is "$.index[*][?(@.name=='Hex')].inner.variant_inner.value" '"4"'
+ // @is "$.index[*][?(@.name=='Hex')].inner.variant_inner.expr" '"0x4"'
+ Hex = 0x4,
+ // @is "$.index[*][?(@.name=='Cast')].inner.variant_inner.value" '"5"'
+ // @is "$.index[*][?(@.name=='Cast')].inner.variant_inner.expr" '"{ _ }"'
+ Cast = 5 as isize,
+ // @is "$.index[*][?(@.name=='PubCall')].inner.variant_inner.value" '"6"'
+ // @is "$.index[*][?(@.name=='PubCall')].inner.variant_inner.expr" '"{ _ }"'
+ PubCall = six(),
+ // @is "$.index[*][?(@.name=='PrivCall')].inner.variant_inner.value" '"7"'
+ // @is "$.index[*][?(@.name=='PrivCall')].inner.variant_inner.expr" '"{ _ }"'
+ PrivCall = seven(),
+ // @is "$.index[*][?(@.name=='PrivConst')].inner.variant_inner.value" '"8"'
+ // @is "$.index[*][?(@.name=='PrivConst')].inner.variant_inner.expr" '"EIGHT"'
+ PrivConst = EIGHT,
+}
+
+pub const THREE: isize = 3;
+const EIGHT: isize = 8;
+
+pub const fn six() -> isize {
+ 6
+}
+const fn seven() -> isize {
+ 7
+}
--- /dev/null
+// ignore-tidy-linelength
+#![feature(repr128)]
+#![allow(incomplete_features)]
+
+#[repr(u64)]
+pub enum U64 {
+ // @is "$.index[*][?(@.name=='U64Min')].inner.variant_inner.value" '"0"'
+ // @is "$.index[*][?(@.name=='U64Min')].inner.variant_inner.expr" '"u64::MIN"'
+ U64Min = u64::MIN,
+ // @is "$.index[*][?(@.name=='U64Max')].inner.variant_inner.value" '"18446744073709551615"'
+ // @is "$.index[*][?(@.name=='U64Max')].inner.variant_inner.expr" '"u64::MAX"'
+ U64Max = u64::MAX,
+}
+
+#[repr(i64)]
+pub enum I64 {
+ // @is "$.index[*][?(@.name=='I64Min')].inner.variant_inner.value" '"-9223372036854775808"'
+ // @is "$.index[*][?(@.name=='I64Min')].inner.variant_inner.expr" '"i64::MIN"'
+ I64Min = i64::MIN,
+ // @is "$.index[*][?(@.name=='I64Max')].inner.variant_inner.value" '"9223372036854775807"'
+ // @is "$.index[*][?(@.name=='I64Max')].inner.variant_inner.expr" '"i64::MAX"'
+ I64Max = i64::MAX,
+}
+
+#[repr(u128)]
+pub enum U128 {
+ // @is "$.index[*][?(@.name=='U128Min')].inner.variant_inner.value" '"0"'
+ // @is "$.index[*][?(@.name=='U128Min')].inner.variant_inner.expr" '"u128::MIN"'
+ U128Min = u128::MIN,
+ // @is "$.index[*][?(@.name=='U128Max')].inner.variant_inner.value" '"340282366920938463463374607431768211455"'
+ // @is "$.index[*][?(@.name=='U128Max')].inner.variant_inner.expr" '"u128::MAX"'
+ U128Max = u128::MAX,
+}
+
+#[repr(i128)]
+pub enum I128 {
+ // @is "$.index[*][?(@.name=='I128Min')].inner.variant_inner.value" '"-170141183460469231731687303715884105728"'
+ // @is "$.index[*][?(@.name=='I128Min')].inner.variant_inner.expr" '"i128::MIN"'
+ I128Min = i128::MIN,
+ // @is "$.index[*][?(@.name=='I128Max')].inner.variant_inner.value" '"170141183460469231731687303715884105727"'
+ // @is "$.index[*][?(@.name=='I128Max')].inner.variant_inner.expr" '"i128::MAX"'
+ I128Max = i128::MAX,
+}
--- /dev/null
+#[repr(u32)]
+pub enum Foo {
+ // @is "$.index[*][?(@.name=='Basic')].inner.variant_inner.value" '"0"'
+ // @is "$.index[*][?(@.name=='Basic')].inner.variant_inner.expr" '"0"'
+ Basic = 0,
+ // @is "$.index[*][?(@.name=='Suffix')].inner.variant_inner.value" '"10"'
+ // @is "$.index[*][?(@.name=='Suffix')].inner.variant_inner.expr" '"10u32"'
+ Suffix = 10u32,
+ // @is "$.index[*][?(@.name=='Underscore')].inner.variant_inner.value" '"100"'
+ // @is "$.index[*][?(@.name=='Underscore')].inner.variant_inner.expr" '"1_0_0"'
+ Underscore = 1_0_0,
+ // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant_inner.value" '"1000"'
+ // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant_inner.expr" '"1_0_0_0u32"'
+ SuffixUnderscore = 1_0_0_0u32,
+}
--- /dev/null
+pub enum Foo {
+ // @is "$.index[*][?(@.name=='Has')].inner.variant_inner" '{"expr":"0", "value":"0"}'
+ Has = 0,
+ // @is "$.index[*][?(@.name=='Doesnt')].inner.variant_inner" null
+ Doesnt,
+ // @is "$.index[*][?(@.name=='AlsoDoesnt')].inner.variant_inner" null
+ AlsoDoesnt,
+ // @is "$.index[*][?(@.name=='AlsoHas')].inner.variant_inner" '{"expr":"44", "value":"44"}'
+ AlsoHas = 44,
+}
help: remove the extra argument
|
LL | extra();
- | ~~~~~~~
+ | ~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/basic.rs:22:5
help: provide the argument
|
LL | missing(/* u32 */);
- | ~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/basic.rs:23:5
help: swap these arguments
|
LL | swapped(1, "");
- | ~~~~~~~~~~~~~~
+ | ~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/basic.rs:24:5
help: reorder these arguments
|
LL | permuted(X {}, Y {}, Z {});
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error[E0057]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/basic.rs:27:5
help: provide the argument
|
LL | closure(/* value */);
- | ~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error: aborting due to 6 previous errors
help: did you mean
|
LL | complex(/* u32 */, &"", /* E */, F::X2, G{}, X {}, Y {}, Z {});
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: remove the extra argument
|
LL | t();
- | ~~~
+ | ~~
error[E0057]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/exotic-calls.rs:7:5
help: remove the extra argument
|
LL | t();
- | ~~~
+ | ~~
error[E0057]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/exotic-calls.rs:16:5
help: remove the extra argument
|
LL | baz()()
- |
+ | ~~
error[E0057]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/exotic-calls.rs:22:5
help: remove the extra argument
|
LL | x();
- | ~~~
+ | ~~
error: aborting due to 4 previous errors
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
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
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
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
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
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
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
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
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
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
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
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
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
help: remove the extra argument
|
LL | two_arg_diff(1, "");
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~
error: aborting due to 14 previous errors
help: provide the argument
|
LL | f(/* usize */, &x, /* usize */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: provide the arguments
|
LL | g((), /* bool */, /* bool */, /* bool */, /* bool */, ());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: remove the extra arguments
|
LL | foo(&&A, D, /* &E */, G);
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: provide the argument
|
LL | (|_, ()| ())(if true {} else {return;}, ());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: provide the argument
|
LL | (|_, ()| ())([return, ()], ());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: provide the argument
|
LL | let _f = f((), main);
- | ~~~~~~~~~~~
+ | ~~~~~~~~~~
error: aborting due to previous error
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
help: provide the arguments
|
LL | complex(1, /* f32 */, /* i32 */, /* f32 */, "");
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 19 previous errors
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
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
help: provide the argument
|
LL | three_args(1, /* f32 */, /* &str */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/mixed_cases.rs:17:3
help: did you mean
|
LL | three_args(1, /* f32 */, "");
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/mixed_cases.rs:20:3
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
help: did you mean
|
LL | three_args(1, /* f32 */, "");
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error: aborting due to 6 previous errors
help: reorder these arguments
|
LL | three_args(1, 1.0, "");
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/permuted_arguments.rs:12:3
help: reorder these arguments
|
LL | many_args(1, 1.0, "", X {}, Y {});
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
help: swap these arguments
|
LL | two_args(1, 1.0);
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:9:3
help: swap these arguments
|
LL | three_args(1, 1.0, "");
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:10:3
help: swap these arguments
|
LL | three_args(1, 1.0, "");
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:11:3
help: swap these arguments
|
LL | three_args(1, 1.0, "");
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:13:3
help: did you mean
|
LL | four_args(1, 1.0, "", X {});
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error: aborting due to 5 previous errors
--- /dev/null
+// check-pass
+// compile-flags: -Zunpretty=expanded
+core::arch::global_asm!("x: .byte 42");
--- /dev/null
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// check-pass
+// compile-flags: -Zunpretty=expanded
+global_asm! ("x: .byte 42");
f1(2u32, 4u32);
//~^ ERROR `u32: Foo` is not satisfied
//~| ERROR `u32: Foo` is not satisfied
+ //~| ERROR `u32: Foo` is not satisfied
}
pub fn f1_uint_int() {
f1(2u32, 4i32);
//~^ ERROR `u32: Foo` is not satisfied
//~| ERROR `u32: Foo` is not satisfied
+ //~| ERROR `u32: Foo` is not satisfied
}
pub fn f2_int() {
LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
| ^^^ required by this bound in `f1`
+error[E0277]: the trait bound `u32: Foo` is not satisfied
+ --> $DIR/associated-types-path-2.rs:29:5
+ |
+LL | f1(2u32, 4u32);
+ | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
+ |
+ = help: the trait `Foo` is implemented for `i32`
+
error[E0277]: the trait bound `u32: Foo` is not satisfied
--> $DIR/associated-types-path-2.rs:29:14
|
= help: the trait `Foo` is implemented for `i32`
error[E0277]: the trait bound `u32: Foo` is not satisfied
- --> $DIR/associated-types-path-2.rs:35:8
+ --> $DIR/associated-types-path-2.rs:36:8
|
LL | f1(2u32, 4i32);
| -- ^^^^ the trait `Foo` is not implemented for `u32`
| ^^^ required by this bound in `f1`
error[E0277]: the trait bound `u32: Foo` is not satisfied
- --> $DIR/associated-types-path-2.rs:35:14
+ --> $DIR/associated-types-path-2.rs:36:5
+ |
+LL | f1(2u32, 4i32);
+ | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
+ |
+ = help: the trait `Foo` is implemented for `i32`
+
+error[E0277]: the trait bound `u32: Foo` is not satisfied
+ --> $DIR/associated-types-path-2.rs:36:14
|
LL | f1(2u32, 4i32);
| ^^^^ the trait `Foo` is not implemented for `u32`
= help: the trait `Foo` is implemented for `i32`
error[E0308]: mismatched types
- --> $DIR/associated-types-path-2.rs:41:18
+ --> $DIR/associated-types-path-2.rs:43:18
|
LL | let _: i32 = f2(2i32);
| --- ^^^^^^^^ expected `i32`, found `u32`
LL | let _: i32 = f2(2i32).try_into().unwrap();
| ++++++++++++++++++++
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
// run-pass
// edition:2018
+// revisions: normal drop-tracking
+// [normal]compile-flags: -Zdrop-tracking=no
+// [drop-tracking]compile-flags: -Zdrop-tracking
#![allow(dead_code)]
use std::future::Future;
LL | (|_| 2333).await;
| ^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future
|
- = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]`
+ = help: the trait `Future` is not implemented for closure `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]`
= note: [closure@$DIR/issue-62009-1.rs:12:6: 12:9] must be a future or must implement `IntoFuture` to be awaited
= note: required for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` to implement `IntoFuture`
help: remove the `.await`
--- /dev/null
+#![feature(rustc_private)]
+extern crate libc;
+
+/// So tests don't have to bring libc in scope themselves
+pub enum SignalHandler {
+ Ignore,
+ Default,
+}
+
+/// Helper to assert that [`libc::SIGPIPE`] has the expected signal handler.
+pub fn assert_sigpipe_handler(expected_handler: SignalHandler) {
+ #[cfg(unix)]
+ #[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "horizon",
+ target_os = "android",
+ )))]
+ {
+ let prev = unsafe { libc::signal(libc::SIGPIPE, libc::SIG_IGN) };
+
+ let expected = match expected_handler {
+ SignalHandler::Ignore => libc::SIG_IGN,
+ SignalHandler::Default => libc::SIG_DFL,
+ };
+ assert_eq!(prev, expected);
+
+ // Unlikely to matter, but restore the old value anyway
+ unsafe { libc::signal(libc::SIGPIPE, prev); };
+ }
+}
--- /dev/null
+#![feature(unix_sigpipe)]
+#![unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute cannot be used at crate level
+
+fn main() {}
--- /dev/null
+error: `unix_sigpipe` attribute cannot be used at crate level
+ --> $DIR/unix_sigpipe-crate.rs:2:1
+ |
+LL | #![unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: perhaps you meant to use an outer attribute
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "sig_ign"]
+#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes
+fn main() {}
--- /dev/null
+error: multiple `unix_sigpipe` attributes
+ --> $DIR/unix_sigpipe-duplicates.rs:4:1
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unix_sigpipe-duplicates.rs:3:1
+ |
+LL | #[unix_sigpipe = "sig_ign"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "sig_ign"]
+fn main() {
+ extern crate sigpipe_utils;
+
+ // #[unix_sigpipe = "sig_ign"] is active, so the legacy behavior of ignoring
+ // SIGPIPE shall be in effect
+ sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
+}
--- /dev/null
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "inherit"]
+fn main() {
+ extern crate sigpipe_utils;
+
+ // #[unix_sigpipe = "inherit"] is active, so SIGPIPE shall NOT be ignored,
+ // instead the default handler shall be installed. (We assume that the
+ // process that runs these tests have the default handler.)
+ sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
+}
--- /dev/null
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe(inherit)] //~ error: malformed `unix_sigpipe` attribute input
+fn main() {}
--- /dev/null
+error: malformed `unix_sigpipe` attribute input
+ --> $DIR/unix_sigpipe-list.rs:3:1
+ |
+LL | #[unix_sigpipe(inherit)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: the following are the possible correct uses
+ |
+LL | #[unix_sigpipe = "inherit|sig_ign|sig_dfl"]
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | #[unix_sigpipe]
+ | ~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
+fn f() {}
+
+fn main() {}
--- /dev/null
+error: `unix_sigpipe` attribute can only be used on `fn main()`
+ --> $DIR/unix_sigpipe-non-main-fn.rs:3:1
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(unix_sigpipe)]
+
+mod m {
+ #[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on root `fn main()`
+ fn main() {}
+}
+
+fn main() {}
--- /dev/null
+error: `unix_sigpipe` attribute can only be used on root `fn main()`
+ --> $DIR/unix_sigpipe-non-root-main.rs:4:5
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+fn main() {
+ extern crate sigpipe_utils;
+
+ // SIGPIPE shall be ignored since #[unix_sigpipe = "..."] is not used
+ sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
+}
--- /dev/null
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+fn main() {
+ extern crate sigpipe_utils;
+
+ // Only #![feature(unix_sigpipe)] is enabled, not #[unix_sigpipe = "..."].
+ // This shall not change any behavior, so we still expect SIGPIPE to be
+ // ignored
+ sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
+}
--- /dev/null
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+#![feature(rustc_attrs)]
+
+#[unix_sigpipe = "sig_dfl"]
+#[rustc_main]
+fn rustc_main() {
+ extern crate sigpipe_utils;
+
+ // #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE handler shall be
+ // SIG_DFL. Note that we have a #[rustc_main], but it should still work.
+ sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
+}
--- /dev/null
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "sig_dfl"]
+fn main() {
+ extern crate sigpipe_utils;
+
+ // #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE shall NOT be ignored, instead
+ // the default handler shall be installed
+ sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
+}
--- /dev/null
+#![feature(start)]
+#![feature(unix_sigpipe)]
+
+#[start]
+#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
+fn custom_start(argc: isize, argv: *const *const u8) -> isize { 0 }
--- /dev/null
+error: `unix_sigpipe` attribute can only be used on `fn main()`
+ --> $DIR/unix_sigpipe-start.rs:5:1
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
+struct S;
+
+fn main() {}
--- /dev/null
+error: `unix_sigpipe` attribute can only be used on `fn main()`
+ --> $DIR/unix_sigpipe-struct.rs:3:1
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "wrong"] //~ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+fn main() {}
--- /dev/null
+error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+ --> $DIR/unix_sigpipe-wrong.rs:3:1
+ |
+LL | #[unix_sigpipe = "wrong"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe] //~ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+fn main() {}
--- /dev/null
+error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+ --> $DIR/unix_sigpipe.rs:3:1
+ |
+LL | #[unix_sigpipe]
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
LL | assert_eq!(foo, y);
| ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
- = help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}`
+ = help: the trait `Debug` is not implemented for fn item `for<'r> fn(&'r i32) -> &'r i32 {foo}`
= help: use parentheses to call the function: `foo(s)`
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
--- /dev/null
+struct State;
+
+fn once(_: impl FnOnce()) {}
+
+fn fill_memory_blocks_mt(state: &mut State) {
+ loop {
+ once(move || {
+ //~^ ERROR use of moved value: `state`
+ fill_segment(state);
+ });
+ }
+}
+
+fn fill_segment(_: &mut State) {}
+
+fn main() {}
--- /dev/null
+error[E0382]: use of moved value: `state`
+ --> $DIR/issue-101119.rs:7:14
+ |
+LL | fn fill_memory_blocks_mt(state: &mut State) {
+ | ----- move occurs because `state` has type `&mut State`, which does not implement the `Copy` trait
+LL | loop {
+LL | once(move || {
+ | ^^^^^^^ value moved into closure here, in previous iteration of loop
+LL |
+LL | fill_segment(state);
+ | ----- use occurs due to use in closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
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
help: provide the argument
|
LL | foo(1, /* u8 */);
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/variadic-ffi-1.rs:23:56
--- /dev/null
+// This test check that #![allow(unexpected_cfgs)] works with --cfg
+//
+// check-pass
+// compile-flags: --cfg=unexpected --check-cfg=names() -Z unstable-options
+
+#![allow(unexpected_cfgs)]
+
+fn main() {}
|
= note: expected values for `feature` are: full, serde
-warning: 2 warnings emitted
+warning: unexpected condition value `rand` for condition name `feature`
+ |
+ = help: was set with `--cfg` but isn't in the `--check-cfg` expected values
+
+warning: 3 warnings emitted
// we correctly lint on the `cfg!` macro and `cfg_attr` attribute.
//
// check-pass
-// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" -Z unstable-options
+// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" --cfg unknown_name -Z unstable-options
#[cfg(windows)]
fn do_windows_stuff() {}
LL | #[cfg_attr(uu, test)]
| ^^
+warning: unexpected condition value `bar` for condition name `feature`
+ |
+ = help: was set with `--cfg` but isn't in the `--check-cfg` expected values
+
+warning: unexpected `unknown_name` as condition name
+ |
+ = help: was set with `--cfg` but isn't in the `--check-cfg` expected names
+
warning: unexpected `cfg` condition name
--> $DIR/mix.rs:35:10
|
|
= note: expected values for `feature` are: foo
-warning: 25 warnings emitted
+warning: 27 warnings emitted
| |
| required by a bound introduced by this call
|
- = help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+ = help: the trait `FnOnce<(&str,)>` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `Option::<T>::map`
--> $SRC_DIR/core/src/option.rs:LL:COL
--- /dev/null
+// check-pass
+
+use std::convert::TryFrom;
+
+pub trait FieldElement {
+ type Integer: TryFrom<usize, Error = std::num::TryFromIntError>;
+
+ fn valid_integer_try_from<N>(i: N) -> Result<Self::Integer, ()>
+ where
+ Self::Integer: TryFrom<N>,
+ {
+ Self::Integer::try_from(i).map_err(|_| ())
+ }
+}
+
+fn main() {}
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;
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;
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:54:30
|
LL | const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
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:55:30
|
LL | const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
help: provide the argument
|
LL | let a = f(/* value */);
- | ~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0057]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/E0057.rs:5:13
help: remove the extra argument
|
LL | let c = f(2);
- | ~~~~
+ | ~~~
error: aborting due to 2 previous errors
help: provide the argument
|
LL | unsafe { printf(/* *const u8 */); }
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: provide the argument
|
LL | f(0, /* &str */);
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/E0061.rs:9:5
help: provide the argument
|
LL | f2(/* u16 */);
- | ~~~~~~~~~~~~~
+ | ~~~~~~~~~~~
error: aborting due to 2 previous errors
| |
| required by a bound introduced by this call
|
- = help: the trait `Fn<()>` is not implemented for `extern "C" fn() {f}`
+ = help: the trait `Fn<()>` is not implemented for fn item `extern "C" fn() {f}`
= note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `is_fn`
--> $DIR/extern-wrong-value-type.rs:4:28
--- /dev/null
+#![crate_type = "bin"]
+
+#[unix_sigpipe = "inherit"] //~ the `#[unix_sigpipe]` attribute is an experimental feature
+fn main () {}
--- /dev/null
+error[E0658]: the `#[unix_sigpipe]` attribute is an experimental feature
+ --> $DIR/feature-gate-unix_sigpipe.rs:3:1
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #97889 <https://github.com/rust-lang/rust/issues/97889> for more information
+ = help: add `#![feature(unix_sigpipe)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
| ^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
+ = note: all function arguments must have a statically known size
= help: unsized fn params are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
- |
-LL | foo(&*x);
- | +
error: aborting due to 2 previous errors
help: provide the argument
|
LL | f(&[f(/* value */)]);
- | ~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error: aborting due to previous error
--- /dev/null
+// See issue #100696.
+// run-fail
+// check-run-results
+fn main() {
+ &""[1..];
+}
--- /dev/null
+thread 'main' panicked at 'byte index 1 is out of bounds of ``', $DIR/const-eval-select-backtrace-std.rs:5:6
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
--- /dev/null
+#![feature(core_intrinsics)]
+// See issue #100696.
+// run-fail
+// check-run-results
+
+#[track_caller]
+fn uhoh() {
+ panic!("Aaah!")
+}
+
+const fn c() {}
+
+fn main() {
+ // safety: this is unsound and just used to test
+ unsafe {
+ std::intrinsics::const_eval_select((), c, uhoh);
+ }
+}
--- /dev/null
+thread 'main' panicked at 'Aaah!', $DIR/const-eval-select-backtrace.rs:16:9
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
const fn not_fn_items() {
const_eval_select((), || {}, || {});
- //~^ ERROR the trait bound
+ //~^ ERROR this argument must be a function item
+ //~| ERROR this argument must be a function item
const_eval_select((), 42, 0xDEADBEEF);
- //~^ ERROR the trait bound
+ //~^ ERROR expected a `FnOnce<()>` closure
//~| ERROR expected a `FnOnce<()>` closure
+ //~| ERROR this argument must be a function item
+ //~| ERROR this argument must be a function item
}
const fn foo(n: i32) -> i32 {
//~^ ERROR type mismatch
}
+const fn non_const_fn() {
+ const_eval_select((1,), bar, bar);
+ //~^ ERROR this argument must be a `const fn`
+}
+
fn main() {}
-error[E0277]: the trait bound `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]: FnOnce<()>` is not satisfied
+error: this argument must be a function item
--> $DIR/const-eval-select-bad.rs:7:27
|
LL | const_eval_select((), || {}, || {});
- | ----------------- ^^^^^ expected an `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`
- | |
- | required by a bound introduced by this call
+ | ^^^^^
|
- = help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`
-note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`, but that implementation is not `const`
- --> $DIR/const-eval-select-bad.rs:7:27
+ = note: expected a function item, found [closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]
+ = help: consult the documentation on `const_eval_select` for more information
+
+error: this argument must be a function item
+ --> $DIR/const-eval-select-bad.rs:7:34
|
LL | const_eval_select((), || {}, || {});
- | ^^^^^
- = note: wrap the `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]` in a closure with no arguments: `|| { /* code */ }`
-note: required by a bound in `const_eval_select`
- --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+ | ^^^^^
|
-LL | F: ~const FnOnce<ARG, Output = RET>,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+ = note: expected a function item, found [closure@$DIR/const-eval-select-bad.rs:7:34: 7:36]
+ = help: consult the documentation on `const_eval_select` for more information
-error[E0277]: the trait bound `{integer}: FnOnce<()>` is not satisfied
- --> $DIR/const-eval-select-bad.rs:9:27
+error: this argument must be a function item
+ --> $DIR/const-eval-select-bad.rs:10:27
+ |
+LL | const_eval_select((), 42, 0xDEADBEEF);
+ | ^^
+ |
+ = note: expected a function item, found {integer}
+ = help: consult the documentation on `const_eval_select` for more information
+
+error[E0277]: expected a `FnOnce<()>` closure, found `{integer}`
+ --> $DIR/const-eval-select-bad.rs:10:27
|
LL | const_eval_select((), 42, 0xDEADBEEF);
| ----------------- ^^ expected an `FnOnce<()>` closure, found `{integer}`
| |
| required by a bound introduced by this call
|
- = help: the trait `~const FnOnce<()>` is not implemented for `{integer}`
+ = help: the trait `FnOnce<()>` is not implemented for `{integer}`
= note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
-LL | F: ~const FnOnce<ARG, Output = RET>,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+LL | F: FnOnce<ARG, Output = RET>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+
+error: this argument must be a function item
+ --> $DIR/const-eval-select-bad.rs:10:31
+ |
+LL | const_eval_select((), 42, 0xDEADBEEF);
+ | ^^^^^^^^^^
+ |
+ = note: expected a function item, found {integer}
+ = help: consult the documentation on `const_eval_select` for more information
error[E0277]: expected a `FnOnce<()>` closure, found `{integer}`
- --> $DIR/const-eval-select-bad.rs:9:31
+ --> $DIR/const-eval-select-bad.rs:10:31
|
LL | const_eval_select((), 42, 0xDEADBEEF);
| ----------------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}`
note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
-LL | G: FnOnce<ARG, Output = RET> + ~const Destruct,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+LL | G: FnOnce<ARG, Output = RET>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
error[E0271]: expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool`
- --> $DIR/const-eval-select-bad.rs:29:34
+ --> $DIR/const-eval-select-bad.rs:32:34
|
LL | const_eval_select((1,), foo, bar);
| ----------------- ^^^ expected `i32`, found `bool`
note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
-LL | G: FnOnce<ARG, Output = RET> + ~const Destruct,
- | ^^^^^^^^^^^^ required by this bound in `const_eval_select`
+LL | G: FnOnce<ARG, Output = RET>,
+ | ^^^^^^^^^^^^ required by this bound in `const_eval_select`
error[E0631]: type mismatch in function arguments
- --> $DIR/const-eval-select-bad.rs:34:32
+ --> $DIR/const-eval-select-bad.rs:37:32
|
LL | const fn foo(n: i32) -> i32 {
| --------------------------- found signature defined here
note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
-LL | F: ~const FnOnce<ARG, Output = RET>,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+LL | F: FnOnce<ARG, Output = RET>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+
+error: this argument must be a `const fn`
+ --> $DIR/const-eval-select-bad.rs:42:29
+ |
+LL | const_eval_select((1,), bar, bar);
+ | ^^^
+ |
+ = help: consult the documentation on `const_eval_select` for more information
-error: aborting due to 5 previous errors
+error: aborting due to 9 previous errors
Some errors have detailed explanations: E0271, E0277, E0631.
For more information about an error, try `rustc --explain E0271`.
help: remove the extra argument
|
LL | |t| f();
- | ~~~
+ | ~~
error: aborting due to previous error
help: provide the argument
|
LL | print_x(/* &dyn Foo<Item = bool> */, /* &str */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: remove the extra argument
|
LL | fn main() { foo(5) }
- | ~~~~~~
+ | ~~~
error: aborting due to previous error
LL | assert_eq!(Foo::Bar, i);
| ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
- = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
+ = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}`
= help: the following other types implement trait `Debug`:
extern "C" fn() -> Ret
extern "C" fn(A, B) -> Ret
LL | assert_eq!(Foo::Bar, i);
| ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
- = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
+ = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}`
= help: the following other types implement trait `Debug`:
extern "C" fn() -> Ret
extern "C" fn(A, B) -> Ret
LL | assert_eq!(a, 0);
| ^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
- = help: the trait `Debug` is not implemented for `fn() -> i32 {a}`
+ = help: the trait `Debug` is not implemented for fn item `fn() -> i32 {a}`
= help: use parentheses to call the function: `a()`
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
--- /dev/null
+struct Argument;
+struct Return;
+
+fn function(_: Argument) -> Return { todo!() }
+
+trait Trait {}
+impl Trait for fn(Argument) -> Return {}
+
+fn takes(_: impl Trait) {}
+
+fn main() {
+ takes(function);
+ //~^ ERROR the trait bound
+ takes(|_: Argument| -> Return { todo!() });
+ //~^ ERROR the trait bound
+}
--- /dev/null
+error[E0277]: the trait bound `fn(Argument) -> Return {function}: Trait` is not satisfied
+ --> $DIR/issue-99875.rs:12:11
+ |
+LL | takes(function);
+ | ----- ^^^^^^^^ the trait `Trait` is not implemented for fn item `fn(Argument) -> Return {function}`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
+note: required by a bound in `takes`
+ --> $DIR/issue-99875.rs:9:18
+ |
+LL | fn takes(_: impl Trait) {}
+ | ^^^^^ required by this bound in `takes`
+
+error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied
+ --> $DIR/issue-99875.rs:14:11
+ |
+LL | takes(|_: Argument| -> Return { todo!() });
+ | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `[closure@$DIR/issue-99875.rs:14:11: 14:34]`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
+note: required by a bound in `takes`
+ --> $DIR/issue-99875.rs:9:18
+ |
+LL | fn takes(_: impl Trait) {}
+ | ^^^^^ required by this bound in `takes`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
fn main() {
let _ = Iterator::next(&mut ());
//~^ ERROR `()` is not an iterator
+ //~| ERROR `()` is not an iterator
+ //~| ERROR `()` is not an iterator
for _ in false {}
//~^ ERROR `bool` is not an iterator
let _ = Iterator::next(&mut ());
//~^ ERROR `()` is not an iterator
+ //~| ERROR `()` is not an iterator
other()
}
let _ = Iterator::next(&mut ());
//~^ ERROR `()` is not an iterator
+ //~| ERROR `()` is not an iterator
+ //~| ERROR `()` is not an iterator
let _ = Iterator::next(&mut ());
//~^ ERROR `()` is not an iterator
+ //~| ERROR `()` is not an iterator
for _ in false {}
//~^ ERROR `bool` is not an iterator
|
= help: the trait `Iterator` is not implemented for `()`
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-28098.rs:2:13
+ |
+LL | let _ = Iterator::next(&mut ());
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+
error[E0277]: `bool` is not an iterator
- --> $DIR/issue-28098.rs:5:14
+ --> $DIR/issue-28098.rs:7:14
|
LL | for _ in false {}
| ^^^^^ `bool` is not an iterator
= note: required for `bool` to implement `IntoIterator`
error[E0277]: `()` is not an iterator
- --> $DIR/issue-28098.rs:8:28
+ --> $DIR/issue-28098.rs:10:28
|
LL | let _ = Iterator::next(&mut ());
| -------------- ^^^^^^^ `()` is not an iterator
= help: the trait `Iterator` is not implemented for `()`
error[E0277]: `()` is not an iterator
- --> $DIR/issue-28098.rs:17:28
+ --> $DIR/issue-28098.rs:10:13
+ |
+LL | let _ = Iterator::next(&mut ());
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-28098.rs:2:13
+ |
+LL | let _ = Iterator::next(&mut ());
+ | ^^^^^^^^^^^^^^ `()` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-28098.rs:20:28
|
LL | let _ = Iterator::next(&mut ());
| -------------- ^^^^^^^ `()` is not an iterator
= help: the trait `Iterator` is not implemented for `()`
error[E0277]: `()` is not an iterator
- --> $DIR/issue-28098.rs:20:28
+ --> $DIR/issue-28098.rs:20:13
+ |
+LL | let _ = Iterator::next(&mut ());
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-28098.rs:25:28
|
LL | let _ = Iterator::next(&mut ());
| -------------- ^^^^^^^ `()` is not an iterator
|
= help: the trait `Iterator` is not implemented for `()`
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-28098.rs:25:13
+ |
+LL | let _ = Iterator::next(&mut ());
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+
error[E0277]: `bool` is not an iterator
- --> $DIR/issue-28098.rs:23:14
+ --> $DIR/issue-28098.rs:29:14
|
LL | for _ in false {}
| ^^^^^ `bool` is not an iterator
= help: the trait `Iterator` is not implemented for `bool`
= note: required for `bool` to implement `IntoIterator`
-error: aborting due to 6 previous errors
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-28098.rs:20:13
+ |
+LL | let _ = Iterator::next(&mut ());
+ | ^^^^^^^^^^^^^^ `()` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+
+error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// run-pass
+// edition:2021
+// check-run-results
+//
+// Drop order tests for let else
+//
+// Mostly this ensures two things:
+// 1. That let and let else temporary drop order is the same.
+// This is a specific design request: https://github.com/rust-lang/rust/pull/93628#issuecomment-1047140316
+// 2. That the else block truly only runs after the
+// temporaries have dropped.
+//
+// We also print some nice tables for an overview by humans.
+// Changes in those tables are considered breakages, but the
+// important properties 1 and 2 are also enforced by the code.
+// This is important as it's easy to update the stdout file
+// with a --bless and miss the impact of that change.
+
+#![feature(let_else)]
+#![allow(irrefutable_let_patterns)]
+
+use std::cell::RefCell;
+use std::rc::Rc;
+
+#[derive(Clone)]
+struct DropAccountant(Rc<RefCell<Vec<Vec<String>>>>);
+
+impl DropAccountant {
+ fn new() -> Self {
+ Self(Default::default())
+ }
+ fn build_droppy(&self, v: u32) -> Droppy<u32> {
+ Droppy(self.clone(), v)
+ }
+ fn build_droppy_enum_none(&self, _v: u32) -> ((), DroppyEnum<u32>) {
+ ((), DroppyEnum::None(self.clone()))
+ }
+ fn new_list(&self, s: impl ToString) {
+ self.0.borrow_mut().push(vec![s.to_string()]);
+ }
+ fn push(&self, s: impl ToString) {
+ let s = s.to_string();
+ let mut accounts = self.0.borrow_mut();
+ accounts.last_mut().unwrap().push(s);
+ }
+ fn print_table(&self) {
+ println!();
+
+ let accounts = self.0.borrow();
+ let before_last = &accounts[accounts.len() - 2];
+ let last = &accounts[accounts.len() - 1];
+ let before_last = get_comma_list(before_last);
+ let last = get_comma_list(last);
+ const LINES: &[&str] = &[
+ "vanilla",
+ "&",
+ "&mut",
+ "move",
+ "fn(this)",
+ "tuple",
+ "array",
+ "ref &",
+ "ref mut &mut",
+ ];
+ let max_len = LINES.iter().map(|v| v.len()).max().unwrap();
+ let max_len_before = before_last.iter().map(|v| v.len()).max().unwrap();
+ let max_len_last = last.iter().map(|v| v.len()).max().unwrap();
+
+ println!(
+ "| {: <max_len$} | {: <max_len_before$} | {: <max_len_last$} |",
+ "construct", before_last[0], last[0]
+ );
+ println!("| {:-<max_len$} | {:-<max_len_before$} | {:-<max_len_last$} |", "", "", "");
+
+ for ((l, l_before), l_last) in
+ LINES.iter().zip(before_last[1..].iter()).zip(last[1..].iter())
+ {
+ println!(
+ "| {: <max_len$} | {: <max_len_before$} | {: <max_len_last$} |",
+ l, l_before, l_last,
+ );
+ }
+ }
+ #[track_caller]
+ fn assert_all_equal_to(&self, st: &str) {
+ let accounts = self.0.borrow();
+ let last = &accounts[accounts.len() - 1];
+ let last = get_comma_list(last);
+ for line in last[1..].iter() {
+ assert_eq!(line.trim(), st.trim());
+ }
+ }
+ #[track_caller]
+ fn assert_equality_last_two_lists(&self) {
+ let accounts = self.0.borrow();
+ let last = &accounts[accounts.len() - 1];
+ let before_last = &accounts[accounts.len() - 2];
+ for (l, b) in last[1..].iter().zip(before_last[1..].iter()) {
+ if !(l == b || l == "n/a" || b == "n/a") {
+ panic!("not equal: '{last:?}' != '{before_last:?}'");
+ }
+ }
+ }
+}
+
+fn get_comma_list(sl: &[String]) -> Vec<String> {
+ std::iter::once(sl[0].clone())
+ .chain(sl[1..].chunks(2).map(|c| c.join(",")))
+ .collect::<Vec<String>>()
+}
+
+struct Droppy<T>(DropAccountant, T);
+
+impl<T> Drop for Droppy<T> {
+ fn drop(&mut self) {
+ self.0.push("drop");
+ }
+}
+
+#[allow(dead_code)]
+enum DroppyEnum<T> {
+ Some(DropAccountant, T),
+ None(DropAccountant),
+}
+
+impl<T> Drop for DroppyEnum<T> {
+ fn drop(&mut self) {
+ match self {
+ DroppyEnum::Some(acc, _inner) => acc,
+ DroppyEnum::None(acc) => acc,
+ }
+ .push("drop");
+ }
+}
+
+macro_rules! nestings_with {
+ ($construct:ident, $binding:pat, $exp:expr) => {
+ // vanilla:
+ $construct!($binding, $exp.1);
+
+ // &:
+ $construct!(&$binding, &$exp.1);
+
+ // &mut:
+ $construct!(&mut $binding, &mut ($exp.1));
+
+ {
+ // move:
+ let w = $exp;
+ $construct!(
+ $binding,
+ {
+ let w = w;
+ w
+ }
+ .1
+ );
+ }
+
+ // fn(this):
+ $construct!($binding, std::convert::identity($exp).1);
+ };
+}
+
+macro_rules! nestings {
+ ($construct:ident, $binding:pat, $exp:expr) => {
+ nestings_with!($construct, $binding, $exp);
+
+ // tuple:
+ $construct!(($binding, 77), ($exp.1, 77));
+
+ // array:
+ $construct!([$binding], [$exp.1]);
+ };
+}
+
+macro_rules! let_else {
+ ($acc:expr, $v:expr, $binding:pat, $build:ident) => {
+ let acc = $acc;
+ let v = $v;
+
+ macro_rules! let_else_construct {
+ ($arg:pat, $exp:expr) => {
+ loop {
+ let $arg = $exp else {
+ acc.push("else");
+ break;
+ };
+ acc.push("body");
+ break;
+ }
+ };
+ }
+ nestings!(let_else_construct, $binding, acc.$build(v));
+ // ref &:
+ let_else_construct!($binding, &acc.$build(v).1);
+
+ // ref mut &mut:
+ let_else_construct!($binding, &mut acc.$build(v).1);
+ };
+}
+
+macro_rules! let_ {
+ ($acc:expr, $binding:tt) => {
+ let acc = $acc;
+
+ macro_rules! let_construct {
+ ($arg:pat, $exp:expr) => {{
+ let $arg = $exp;
+ acc.push("body");
+ }};
+ }
+ let v = 0;
+ {
+ nestings_with!(let_construct, $binding, acc.build_droppy(v));
+ }
+ acc.push("n/a");
+ acc.push("n/a");
+ acc.push("n/a");
+ acc.push("n/a");
+
+ // ref &:
+ let_construct!($binding, &acc.build_droppy(v).1);
+
+ // ref mut &mut:
+ let_construct!($binding, &mut acc.build_droppy(v).1);
+ };
+}
+
+fn main() {
+ let acc = DropAccountant::new();
+
+ println!(" --- matching cases ---");
+
+ // Ensure that let and let else have the same behaviour
+ acc.new_list("let _");
+ let_!(&acc, _);
+ acc.new_list("let else _");
+ let_else!(&acc, 0, _, build_droppy);
+ acc.assert_equality_last_two_lists();
+ acc.print_table();
+
+ // Ensure that let and let else have the same behaviour
+ acc.new_list("let _v");
+ let_!(&acc, _v);
+ acc.new_list("let else _v");
+ let_else!(&acc, 0, _v, build_droppy);
+ acc.assert_equality_last_two_lists();
+ acc.print_table();
+
+ println!();
+
+ println!(" --- mismatching cases ---");
+
+ acc.new_list("let else _ mismatch");
+ let_else!(&acc, 1, DroppyEnum::Some(_, _), build_droppy_enum_none);
+ acc.new_list("let else _v mismatch");
+ let_else!(&acc, 1, DroppyEnum::Some(_, _v), build_droppy_enum_none);
+ acc.print_table();
+ // This ensures that we always drop before visiting the else case
+ acc.assert_all_equal_to("drop,else");
+
+ acc.new_list("let else 0 mismatch");
+ let_else!(&acc, 1, 0, build_droppy);
+ acc.new_list("let else 0 mismatch");
+ let_else!(&acc, 1, 0, build_droppy);
+ acc.print_table();
+ // This ensures that we always drop before visiting the else case
+ acc.assert_all_equal_to("drop,else");
+}
--- /dev/null
+ --- matching cases ---
+
+| construct | let _ | let else _ |
+| ------------ | --------- | ---------- |
+| vanilla | drop,body | drop,body |
+| & | body,drop | body,drop |
+| &mut | body,drop | body,drop |
+| move | drop,body | drop,body |
+| fn(this) | drop,body | drop,body |
+| tuple | n/a,n/a | drop,body |
+| array | n/a,n/a | drop,body |
+| ref & | body,drop | body,drop |
+| ref mut &mut | body,drop | body,drop |
+
+| construct | let _v | let else _v |
+| ------------ | --------- | ----------- |
+| vanilla | drop,body | drop,body |
+| & | body,drop | body,drop |
+| &mut | body,drop | body,drop |
+| move | drop,body | drop,body |
+| fn(this) | drop,body | drop,body |
+| tuple | n/a,n/a | drop,body |
+| array | n/a,n/a | drop,body |
+| ref & | body,drop | body,drop |
+| ref mut &mut | body,drop | body,drop |
+
+ --- mismatching cases ---
+
+| construct | let else _ mismatch | let else _v mismatch |
+| ------------ | ------------------- | -------------------- |
+| vanilla | drop,else | drop,else |
+| & | drop,else | drop,else |
+| &mut | drop,else | drop,else |
+| move | drop,else | drop,else |
+| fn(this) | drop,else | drop,else |
+| tuple | drop,else | drop,else |
+| array | drop,else | drop,else |
+| ref & | drop,else | drop,else |
+| ref mut &mut | drop,else | drop,else |
+
+| construct | let else 0 mismatch | let else 0 mismatch |
+| ------------ | ------------------- | ------------------- |
+| vanilla | drop,else | drop,else |
+| & | drop,else | drop,else |
+| &mut | drop,else | drop,else |
+| move | drop,else | drop,else |
+| fn(this) | drop,else | drop,else |
+| tuple | drop,else | drop,else |
+| array | drop,else | drop,else |
+| ref & | drop,else | drop,else |
+| ref mut &mut | drop,else | drop,else |
help: provide the argument
|
LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter(/* &u8 */) }
- | ~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/issue-26638.rs:5:47
--- /dev/null
+// check-pass
+// edition:2021
+#![deny(rust_2021_compatibility)]
+
+pub struct Warns {
+ // `Arc` has significant drop
+ _significant_drop: std::sync::Arc<()>,
+ field: String,
+}
+
+pub fn test(w: Warns) {
+ _ = || drop(w.field);
+}
+
+fn main() {}
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
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
help: provide the argument
|
LL | .two(0, /* isize */);
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~
error[E0599]: `Foo` is not an iterator
--> $DIR/method-call-err-msg.rs:19:7
help: provide the arguments
|
LL | y.three::<usize>(/* usize */, /* usize */, /* usize */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 5 previous errors
--- /dev/null
+// check-pass
+pub trait Backend {
+ type DescriptorSetLayout;
+}
+
+pub struct Back;
+
+impl Backend for Back {
+ type DescriptorSetLayout = u32;
+}
+
+pub struct HalSetLayouts {
+ vertex_layout: <Back as Backend>::DescriptorSetLayout,
+}
+
+impl HalSetLayouts {
+ pub fn iter<DSL>(self) -> DSL
+ where
+ Back: Backend<DescriptorSetLayout = DSL>,
+ {
+ self.vertex_layout
+ }
+}
+
+fn main() {}
help: provide the argument
|
LL | let ans = s(/* isize */);
- | ~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0057]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/overloaded-calls-bad.rs:31:15
help: remove the extra argument
|
LL | let ans = s(/* isize */);
- | ~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error: aborting due to 3 previous errors
--> $DIR/namespace-mix.rs:56:11
|
LL | check(m3::TS);
- | ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> c::TS {c::TS}`
| |
| required by a bound introduced by this call
|
--> $DIR/namespace-mix.rs:62:11
|
LL | check(xm3::TS);
- | ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
| |
| required by a bound introduced by this call
|
--> $DIR/namespace-mix.rs:122:11
|
LL | check(m9::TV);
- | ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> c::E {c::E::TV}`
| |
| required by a bound introduced by this call
|
--> $DIR/namespace-mix.rs:128:11
|
LL | check(xm9::TV);
- | ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
| |
| required by a bound introduced by this call
|
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
help: provide the arguments
|
LL | bar(1, 2, 3, /* i32 */, /* i32 */, /* i32 */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
#![feature(rustc_attrs)]
#[rustc_object_lifetime_default]
-struct A<T>(T); //~ ERROR BaseDefault
+struct A<
+ T, //~ ERROR BaseDefault
+>(T);
#[rustc_object_lifetime_default]
-struct B<'a,T>(&'a (), T); //~ ERROR BaseDefault
+struct B<
+ 'a,
+ T, //~ ERROR BaseDefault
+>(&'a (), T);
#[rustc_object_lifetime_default]
-struct C<'a,T:'a>(&'a T); //~ ERROR 'a
+struct C<
+ 'a,
+ T: 'a, //~ ERROR 'a
+>(&'a T);
#[rustc_object_lifetime_default]
-struct D<'a,'b,T:'a+'b>(&'a T, &'b T); //~ ERROR Ambiguous
+struct D<
+ 'a,
+ 'b,
+ T: 'a + 'b, //~ ERROR Ambiguous
+>(&'a T, &'b T);
#[rustc_object_lifetime_default]
-struct E<'a,'b:'a,T:'b>(&'a T, &'b T); //~ ERROR 'b
+struct E<
+ 'a,
+ 'b: 'a,
+ T: 'b, //~ ERROR 'b
+>(&'a T, &'b T);
#[rustc_object_lifetime_default]
-struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U); //~ ERROR 'a,'b
+struct F<
+ 'a,
+ 'b,
+ T: 'a, //~ ERROR 'a
+ U: 'b, //~ ERROR 'b
+>(&'a T, &'b U);
#[rustc_object_lifetime_default]
-struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U); //~ ERROR 'a,Ambiguous
-
-fn main() { }
+struct G<
+ 'a,
+ 'b,
+ T: 'a, //~ ERROR 'a
+ U: 'a + 'b, //~ ERROR Ambiguous
+>(&'a T, &'b U);
+
+fn main() {}
error: BaseDefault
- --> $DIR/object-lifetime-default.rs:4:1
+ --> $DIR/object-lifetime-default.rs:5:5
|
-LL | struct A<T>(T);
- | ^^^^^^^^^^^^^^^
+LL | T,
+ | ^
error: BaseDefault
- --> $DIR/object-lifetime-default.rs:7:1
+ --> $DIR/object-lifetime-default.rs:11:5
|
-LL | struct B<'a,T>(&'a (), T);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | T,
+ | ^
error: 'a
- --> $DIR/object-lifetime-default.rs:10:1
+ --> $DIR/object-lifetime-default.rs:17:5
|
-LL | struct C<'a,T:'a>(&'a T);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | T: 'a,
+ | ^
error: Ambiguous
- --> $DIR/object-lifetime-default.rs:13:1
+ --> $DIR/object-lifetime-default.rs:24:5
|
-LL | struct D<'a,'b,T:'a+'b>(&'a T, &'b T);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | T: 'a + 'b,
+ | ^
error: 'b
- --> $DIR/object-lifetime-default.rs:16:1
+ --> $DIR/object-lifetime-default.rs:31:5
|
-LL | struct E<'a,'b:'a,T:'b>(&'a T, &'b T);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | T: 'b,
+ | ^
-error: 'a,'b
- --> $DIR/object-lifetime-default.rs:19:1
+error: 'a
+ --> $DIR/object-lifetime-default.rs:38:5
+ |
+LL | T: 'a,
+ | ^
+
+error: 'b
+ --> $DIR/object-lifetime-default.rs:39:5
|
-LL | struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | U: 'b,
+ | ^
-error: 'a,Ambiguous
- --> $DIR/object-lifetime-default.rs:22:1
+error: 'a
+ --> $DIR/object-lifetime-default.rs:46:5
+ |
+LL | T: 'a,
+ | ^
+
+error: Ambiguous
+ --> $DIR/object-lifetime-default.rs:47:5
|
-LL | struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | U: 'a + 'b,
+ | ^
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors
+++ /dev/null
-// Test scope annotations from `enclosing_scope` parameter
-
-#![feature(rustc_attrs)]
-
-#[rustc_on_unimplemented(enclosing_scope="in this scope")]
-trait Trait{}
-
-struct Foo;
-
-fn f<T: Trait>(x: T) {}
-
-fn main() {
- let x = || {
- f(Foo{}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
- let y = || {
- f(Foo{}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
- };
- };
-
- {
- {
- f(Foo{}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
- }
- }
-
- f(Foo{}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
-}
+++ /dev/null
-error[E0277]: the trait bound `Foo: Trait` is not satisfied
- --> $DIR/enclosing-scope.rs:14:11
- |
-LL | let x = || {
- | _____________-
-LL | | f(Foo{});
- | | - ^^^^^ the trait `Trait` is not implemented for `Foo`
- | | |
- | | required by a bound introduced by this call
-LL | | let y = || {
-LL | | f(Foo{});
-LL | | };
-LL | | };
- | |_____- in this scope
- |
-note: required by a bound in `f`
- --> $DIR/enclosing-scope.rs:10:9
- |
-LL | fn f<T: Trait>(x: T) {}
- | ^^^^^ required by this bound in `f`
-
-error[E0277]: the trait bound `Foo: Trait` is not satisfied
- --> $DIR/enclosing-scope.rs:16:15
- |
-LL | let y = || {
- | _________________-
-LL | | f(Foo{});
- | | - ^^^^^ the trait `Trait` is not implemented for `Foo`
- | | |
- | | required by a bound introduced by this call
-LL | | };
- | |_________- in this scope
- |
-note: required by a bound in `f`
- --> $DIR/enclosing-scope.rs:10:9
- |
-LL | fn f<T: Trait>(x: T) {}
- | ^^^^^ required by this bound in `f`
-
-error[E0277]: the trait bound `Foo: Trait` is not satisfied
- --> $DIR/enclosing-scope.rs:22:15
- |
-LL | / fn main() {
-LL | | let x = || {
-LL | | f(Foo{});
-LL | | let y = || {
-... |
-LL | | f(Foo{});
- | | - ^^^^^ the trait `Trait` is not implemented for `Foo`
- | | |
- | | required by a bound introduced by this call
-... |
-LL | | f(Foo{});
-LL | | }
- | |_- in this scope
- |
-note: required by a bound in `f`
- --> $DIR/enclosing-scope.rs:10:9
- |
-LL | fn f<T: Trait>(x: T) {}
- | ^^^^^ required by this bound in `f`
-
-error[E0277]: the trait bound `Foo: Trait` is not satisfied
- --> $DIR/enclosing-scope.rs:26:7
- |
-LL | / fn main() {
-LL | | let x = || {
-LL | | f(Foo{});
-LL | | let y = || {
-... |
-LL | | f(Foo{});
- | | - ^^^^^ the trait `Trait` is not implemented for `Foo`
- | | |
- | | required by a bound introduced by this call
-LL | | }
- | |_- in this scope
- |
-note: required by a bound in `f`
- --> $DIR/enclosing-scope.rs:10:9
- |
-LL | fn f<T: Trait>(x: T) {}
- | ^^^^^ required by this bound in `f`
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
fn main() {
Index::index(&[] as &[i32], 2u32);
//~^ ERROR E0277
+ //~| ERROR E0277
+ //~| ERROR E0277
Index::index(&[] as &[i32], Foo(2u32));
//~^ ERROR E0277
+ //~| ERROR E0277
+ //~| ERROR E0277
Index::index(&[] as &[i32], Bar(2u32));
//~^ ERROR E0277
+ //~| ERROR E0277
+ //~| ERROR E0277
}
<[i32] as Index<Bar<usize>>>
<[i32] as Index<Foo<usize>>>
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+ --> $DIR/multiple-impls.rs:33:5
+ |
+LL | Index::index(&[] as &[i32], 2u32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message
+ |
+ = help: the trait `Index<u32>` is not implemented for `[i32]`
+ = help: the following other types implement trait `Index<Idx>`:
+ <[i32] as Index<Bar<usize>>>
+ <[i32] as Index<Foo<usize>>>
+
error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
- --> $DIR/multiple-impls.rs:35:33
+ --> $DIR/multiple-impls.rs:37:33
|
LL | Index::index(&[] as &[i32], Foo(2u32));
| ------------ ^^^^^^^^^ on impl for Foo
<[i32] as Index<Bar<usize>>>
<[i32] as Index<Foo<usize>>>
+error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
+ --> $DIR/multiple-impls.rs:37:5
+ |
+LL | Index::index(&[] as &[i32], Foo(2u32));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo
+ |
+ = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
+ = help: the following other types implement trait `Index<Idx>`:
+ <[i32] as Index<Bar<usize>>>
+ <[i32] as Index<Foo<usize>>>
+
error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
- --> $DIR/multiple-impls.rs:37:33
+ --> $DIR/multiple-impls.rs:41:33
|
LL | Index::index(&[] as &[i32], Bar(2u32));
| ------------ ^^^^^^^^^ on impl for Bar
<[i32] as Index<Bar<usize>>>
<[i32] as Index<Foo<usize>>>
-error: aborting due to 3 previous errors
+error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
+ --> $DIR/multiple-impls.rs:41:5
+ |
+LL | Index::index(&[] as &[i32], Bar(2u32));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar
+ |
+ = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
+ = help: the following other types implement trait `Index<Idx>`:
+ <[i32] as Index<Bar<usize>>>
+ <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+ --> $DIR/multiple-impls.rs:33:5
+ |
+LL | Index::index(&[] as &[i32], 2u32);
+ | ^^^^^^^^^^^^ trait message
+ |
+ = help: the trait `Index<u32>` is not implemented for `[i32]`
+ = help: the following other types implement trait `Index<Idx>`:
+ <[i32] as Index<Bar<usize>>>
+ <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
+ --> $DIR/multiple-impls.rs:37:5
+ |
+LL | Index::index(&[] as &[i32], Foo(2u32));
+ | ^^^^^^^^^^^^ on impl for Foo
+ |
+ = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
+ = help: the following other types implement trait `Index<Idx>`:
+ <[i32] as Index<Bar<usize>>>
+ <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
+ --> $DIR/multiple-impls.rs:41:5
+ |
+LL | Index::index(&[] as &[i32], Bar(2u32));
+ | ^^^^^^^^^^^^ on impl for Bar
+ |
+ = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
+ = help: the following other types implement trait `Index<Idx>`:
+ <[i32] as Index<Bar<usize>>>
+ <[i32] as Index<Foo<usize>>>
+
+error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0277`.
fn main() {
Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
//~^ ERROR E0277
+ //~| ERROR E0277
+ //~| ERROR E0277
}
= help: the trait `Index<u32>` is not implemented for `[i32]`
= help: the trait `Index<usize>` is implemented for `[i32]`
-error: aborting due to previous error
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+ --> $DIR/on-impl.rs:22:5
+ |
+LL | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+ |
+ = help: the trait `Index<u32>` is not implemented for `[i32]`
+ = help: the trait `Index<usize>` is implemented for `[i32]`
+
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+ --> $DIR/on-impl.rs:22:5
+ |
+LL | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+ | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+ |
+ = help: the trait `Index<u32>` is not implemented for `[i32]`
+ = help: the trait `Index<usize>` is implemented for `[i32]`
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// Test scope annotations from `parent_label` parameter
+
+#![feature(rustc_attrs)]
+
+#[rustc_on_unimplemented(parent_label = "in this scope")]
+trait Trait {}
+
+struct Foo;
+
+fn f<T: Trait>(x: T) {}
+
+fn main() {
+ let x = || {
+ f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+ let y = || {
+ f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+ };
+ };
+
+ {
+ {
+ f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+ }
+ }
+
+ f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+}
--- /dev/null
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+ --> $DIR/parent-label.rs:14:11
+ |
+LL | let x = || {
+ | -- in this scope
+LL | f(Foo {});
+ | - ^^^^^^ the trait `Trait` is not implemented for `Foo`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `f`
+ --> $DIR/parent-label.rs:10:9
+ |
+LL | fn f<T: Trait>(x: T) {}
+ | ^^^^^ required by this bound in `f`
+
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+ --> $DIR/parent-label.rs:16:15
+ |
+LL | let y = || {
+ | -- in this scope
+LL | f(Foo {});
+ | - ^^^^^^ the trait `Trait` is not implemented for `Foo`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `f`
+ --> $DIR/parent-label.rs:10:9
+ |
+LL | fn f<T: Trait>(x: T) {}
+ | ^^^^^ required by this bound in `f`
+
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+ --> $DIR/parent-label.rs:22:15
+ |
+LL | fn main() {
+ | --------- in this scope
+...
+LL | f(Foo {});
+ | - ^^^^^^ the trait `Trait` is not implemented for `Foo`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `f`
+ --> $DIR/parent-label.rs:10:9
+ |
+LL | fn f<T: Trait>(x: T) {}
+ | ^^^^^ required by this bound in `f`
+
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+ --> $DIR/parent-label.rs:26:7
+ |
+LL | fn main() {
+ | --------- in this scope
+...
+LL | f(Foo {});
+ | - ^^^^^^ the trait `Trait` is not implemented for `Foo`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `f`
+ --> $DIR/parent-label.rs:10:9
+ |
+LL | fn f<T: Trait>(x: T) {}
+ | ^^^^^ required by this bound in `f`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
pub fn expand_expr_is(input: TokenStream) -> TokenStream {
let mut iter = input.into_iter();
let mut expected_tts = Vec::new();
- loop {
+ let comma = loop {
match iter.next() {
- Some(TokenTree::Punct(ref p)) if p.as_char() == ',' => break,
+ Some(TokenTree::Punct(p)) if p.as_char() == ',' => break p,
Some(tt) => expected_tts.push(tt),
None => panic!("expected comma"),
}
- }
+ };
+
+ // Make sure that `Ident` and `Literal` objects from this proc-macro's
+ // environment are not invalidated when `expand_expr` recursively invokes
+ // another macro by taking a local copy, and checking it after the fact.
+ let pre_expand_span = comma.span();
+ let pre_expand_ident = Ident::new("ident", comma.span());
+ let pre_expand_literal = Literal::string("literal");
+ let pre_expand_call_site = Span::call_site();
let expected = expected_tts.into_iter().collect::<TokenStream>();
let expanded = iter.collect::<TokenStream>().expand_expr().expect("expand_expr failed");
// Also compare the raw tts to make sure they line up.
assert_ts_eq(&expected, &expanded);
+ assert!(comma.span().eq(&pre_expand_span), "pre-expansion span is still equal");
+ assert_eq!(pre_expand_ident.to_string(), "ident", "pre-expansion identifier is still valid");
+ assert_eq!(
+ pre_expand_literal.to_string(),
+ "\"literal\"",
+ "pre-expansion literal is still valid"
+ );
+ assert!(Span::call_site().eq(&pre_expand_call_site), "pre-expansion call-site is still equal");
+
TokenStream::new()
}
| |_call the function in a closure: `|| unsafe { /* code */ }`
| required by a bound introduced by this call
|
- = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
+ = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for fn item `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `ProcMacro::custom_derive`
--> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
help: remove the extra argument
|
LL | std::mem::size_of();
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~
error: aborting due to 3 previous errors
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> $DIR/disallowed-positions.rs:132:19
|
-LL | / fn nested_within_if_expr() {
-LL | | if &let 0 = 0 {}
-LL | |
-LL | |
-... |
-LL | | if (let 0 = 0)? {}
- | | ^ cannot use the `?` operator in a function that returns `()`
-... |
-LL | |
-LL | | }
- | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn nested_within_if_expr() {
+ | -------------------------- this function should return `Result` or `Option` to accept `?`
+...
+LL | if (let 0 = 0)? {}
+ | ^ cannot use the `?` operator in a function that returns `()`
|
= help: the trait `FromResidual<_>` is not implemented for `()`
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> $DIR/disallowed-positions.rs:224:22
|
-LL | / fn nested_within_while_expr() {
-LL | | while &let 0 = 0 {}
-LL | |
-LL | |
-... |
-LL | | while (let 0 = 0)? {}
- | | ^ cannot use the `?` operator in a function that returns `()`
-... |
-LL | |
-LL | | }
- | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn nested_within_while_expr() {
+ | ----------------------------- this function should return `Result` or `Option` to accept `?`
+...
+LL | while (let 0 = 0)? {}
+ | ^ cannot use the `?` operator in a function that returns `()`
|
= help: the trait `FromResidual<_>` is not implemented for `()`
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> $DIR/disallowed-positions.rs:325:16
|
-LL | / fn outside_if_and_while_expr() {
-LL | | &let 0 = 0;
-LL | |
-LL | |
-... |
-LL | | (let 0 = 0)?;
- | | ^ cannot use the `?` operator in a function that returns `()`
-... |
-LL | |
-LL | | }
- | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn outside_if_and_while_expr() {
+ | ------------------------------ this function should return `Result` or `Option` to accept `?`
+...
+LL | (let 0 = 0)?;
+ | ^ cannot use the `?` operator in a function that returns `()`
|
= help: the trait `FromResidual<_>` is not implemented for `()`
| |
| required by a bound introduced by this call
|
- = help: the trait `Fn<()>` is not implemented for `fn() {foo}`
+ = help: the trait `Fn<()>` is not implemented for fn item `fn() {foo}`
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call`
| |
| required by a bound introduced by this call
|
- = help: the trait `FnMut<()>` is not implemented for `fn() {foo}`
+ = help: the trait `FnMut<()>` is not implemented for fn item `fn() {foo}`
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call_mut`
| |
| required by a bound introduced by this call
|
- = help: the trait `FnOnce<()>` is not implemented for `fn() {foo}`
+ = help: the trait `FnOnce<()>` is not implemented for fn item `fn() {foo}`
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call_once`
| |
| required by a bound introduced by this call
|
- = help: the trait `Fn<()>` is not implemented for `unsafe fn() {foo_unsafe}`
+ = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call`
| |
| required by a bound introduced by this call
|
- = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {foo_unsafe}`
+ = help: the trait `FnMut<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call_mut`
| |
| required by a bound introduced by this call
|
- = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {foo_unsafe}`
+ = help: the trait `FnOnce<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call_once`
help: remove the extra argument
|
LL | foo(Some(42), 2);
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/issue-34264.rs:8:13
help: remove the extra argument
|
LL | bar(1, 2);
- | ~~~~~~~~~
+ | ~~~~~~
error: aborting due to 6 previous errors
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
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
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
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
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
help: provide the argument
|
LL | S.generic::<()>(());
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~
error: aborting due to 6 previous errors
-
-PRE EXPANSION AST STATS
-
-Name Accumulated Size Count Item Size
-----------------------------------------------------------------
-ExprField 48 ( 0.6%) 1 48
-Crate 56 ( 0.7%) 1 56
-Attribute 64 ( 0.8%) 2 32
-- Normal 32 ( 0.4%) 1
-- DocComment 32 ( 0.4%) 1
-GenericArgs 64 ( 0.8%) 1 64
-- AngleBracketed 64 ( 0.8%) 1
-Local 72 ( 0.9%) 1 72
-WherePredicate 72 ( 0.9%) 1 72
-- BoundPredicate 72 ( 0.9%) 1
-Arm 96 ( 1.1%) 2 48
-ForeignItem 96 ( 1.1%) 1 96
-- Fn 96 ( 1.1%) 1
-FieldDef 160 ( 1.9%) 2 80
-Stmt 160 ( 1.9%) 5 32
-- Local 32 ( 0.4%) 1
-- MacCall 32 ( 0.4%) 1
-- Expr 96 ( 1.1%) 3
-Param 160 ( 1.9%) 4 40
-FnDecl 200 ( 2.4%) 5 40
-Variant 240 ( 2.8%) 2 120
-Block 288 ( 3.4%) 6 48
-GenericBound 352 ( 4.2%) 4 88
-- Trait 352 ( 4.2%) 4
-AssocItem 416 ( 4.9%) 4 104
-- TyAlias 208 ( 2.5%) 2
-- Fn 208 ( 2.5%) 2
-GenericParam 520 ( 6.1%) 5 104
-PathSegment 720 ( 8.5%) 30 24
-Expr 832 ( 9.8%) 8 104
-- Path 104 ( 1.2%) 1
-- Match 104 ( 1.2%) 1
-- Struct 104 ( 1.2%) 1
-- Lit 208 ( 2.5%) 2
-- Block 312 ( 3.7%) 3
-Pat 840 ( 9.9%) 7 120
-- Struct 120 ( 1.4%) 1
-- Wild 120 ( 1.4%) 1
-- Ident 600 ( 7.1%) 5
-Ty 1_344 (15.9%) 14 96
-- Rptr 96 ( 1.1%) 1
-- Ptr 96 ( 1.1%) 1
-- ImplicitSelf 192 ( 2.3%) 2
-- Path 960 (11.4%) 10
-Item 1_656 (19.6%) 9 184
-- Trait 184 ( 2.2%) 1
-- Enum 184 ( 2.2%) 1
-- ForeignMod 184 ( 2.2%) 1
-- Impl 184 ( 2.2%) 1
-- Fn 368 ( 4.4%) 2
-- Use 552 ( 6.5%) 3
-----------------------------------------------------------------
-Total 8_456
-
-
-POST EXPANSION AST STATS
-
-Name Accumulated Size Count Item Size
-----------------------------------------------------------------
-ExprField 48 ( 0.5%) 1 48
-Crate 56 ( 0.6%) 1 56
-GenericArgs 64 ( 0.7%) 1 64
-- AngleBracketed 64 ( 0.7%) 1
-Local 72 ( 0.8%) 1 72
-WherePredicate 72 ( 0.8%) 1 72
-- BoundPredicate 72 ( 0.8%) 1
-Arm 96 ( 1.0%) 2 48
-ForeignItem 96 ( 1.0%) 1 96
-- Fn 96 ( 1.0%) 1
-InlineAsm 120 ( 1.3%) 1 120
-Attribute 128 ( 1.4%) 4 32
-- DocComment 32 ( 0.3%) 1
-- Normal 96 ( 1.0%) 3
-FieldDef 160 ( 1.7%) 2 80
-Stmt 160 ( 1.7%) 5 32
-- Local 32 ( 0.3%) 1
-- Semi 32 ( 0.3%) 1
-- Expr 96 ( 1.0%) 3
-Param 160 ( 1.7%) 4 40
-FnDecl 200 ( 2.2%) 5 40
-Variant 240 ( 2.6%) 2 120
-Block 288 ( 3.1%) 6 48
-GenericBound 352 ( 3.8%) 4 88
-- Trait 352 ( 3.8%) 4
-AssocItem 416 ( 4.5%) 4 104
-- TyAlias 208 ( 2.3%) 2
-- Fn 208 ( 2.3%) 2
-GenericParam 520 ( 5.7%) 5 104
-PathSegment 792 ( 8.6%) 33 24
-Pat 840 ( 9.1%) 7 120
-- Struct 120 ( 1.3%) 1
-- Wild 120 ( 1.3%) 1
-- Ident 600 ( 6.5%) 5
-Expr 936 (10.2%) 9 104
-- Path 104 ( 1.1%) 1
-- Match 104 ( 1.1%) 1
-- Struct 104 ( 1.1%) 1
-- InlineAsm 104 ( 1.1%) 1
-- Lit 208 ( 2.3%) 2
-- Block 312 ( 3.4%) 3
-Ty 1_344 (14.6%) 14 96
-- Rptr 96 ( 1.0%) 1
-- Ptr 96 ( 1.0%) 1
-- ImplicitSelf 192 ( 2.1%) 2
-- Path 960 (10.5%) 10
-Item 2_024 (22.0%) 11 184
-- Trait 184 ( 2.0%) 1
-- Enum 184 ( 2.0%) 1
-- ExternCrate 184 ( 2.0%) 1
-- ForeignMod 184 ( 2.0%) 1
-- Impl 184 ( 2.0%) 1
-- Fn 368 ( 4.0%) 2
-- Use 736 ( 8.0%) 4
-----------------------------------------------------------------
-Total 9_184
-
-
-HIR STATS
-
-Name Accumulated Size Count Item Size
-----------------------------------------------------------------
-Param 64 ( 0.7%) 2 32
-Local 64 ( 0.7%) 1 64
-ForeignItem 72 ( 0.8%) 1 72
-FieldDef 96 ( 1.0%) 2 48
-Arm 96 ( 1.0%) 2 48
-Stmt 96 ( 1.0%) 3 32
-FnDecl 120 ( 1.3%) 3 40
-Attribute 128 ( 1.4%) 4 32
-Lifetime 128 ( 1.4%) 4 32
-Variant 160 ( 1.7%) 2 80
-ImplItem 176 ( 1.9%) 2 88
-GenericBound 192 ( 2.1%) 4 48
-TraitItem 192 ( 2.1%) 2 96
-WherePredicate 216 ( 2.3%) 3 72
-Block 288 ( 3.1%) 6 48
-QPath 408 ( 4.4%) 17 24
-Pat 440 ( 4.8%) 5 88
-Expr 672 ( 7.3%) 12 56
-Item 960 (10.4%) 12 80
-Ty 1_152 (12.4%) 16 72
-Path 1_296 (14.0%) 27 48
-PathSegment 2_240 (24.2%) 40 56
-----------------------------------------------------------------
-Total 9_256
-
+ast-stats-1 PRE EXPANSION AST STATS
+ast-stats-1 Name Accumulated Size Count Item Size
+ast-stats-1 ----------------------------------------------------------------
+ast-stats-1 ExprField 48 ( 0.6%) 1 48
+ast-stats-1 Crate 56 ( 0.7%) 1 56
+ast-stats-1 Attribute 64 ( 0.8%) 2 32
+ast-stats-1 - Normal 32 ( 0.4%) 1
+ast-stats-1 - DocComment 32 ( 0.4%) 1
+ast-stats-1 GenericArgs 64 ( 0.8%) 1 64
+ast-stats-1 - AngleBracketed 64 ( 0.8%) 1
+ast-stats-1 Local 72 ( 0.9%) 1 72
+ast-stats-1 WherePredicate 72 ( 0.9%) 1 72
+ast-stats-1 - BoundPredicate 72 ( 0.9%) 1
+ast-stats-1 Arm 96 ( 1.1%) 2 48
+ast-stats-1 ForeignItem 96 ( 1.1%) 1 96
+ast-stats-1 - Fn 96 ( 1.1%) 1
+ast-stats-1 FieldDef 160 ( 1.9%) 2 80
+ast-stats-1 Stmt 160 ( 1.9%) 5 32
+ast-stats-1 - Local 32 ( 0.4%) 1
+ast-stats-1 - MacCall 32 ( 0.4%) 1
+ast-stats-1 - Expr 96 ( 1.1%) 3
+ast-stats-1 Param 160 ( 1.9%) 4 40
+ast-stats-1 FnDecl 200 ( 2.4%) 5 40
+ast-stats-1 Variant 240 ( 2.8%) 2 120
+ast-stats-1 Block 288 ( 3.4%) 6 48
+ast-stats-1 GenericBound 352 ( 4.2%) 4 88
+ast-stats-1 - Trait 352 ( 4.2%) 4
+ast-stats-1 AssocItem 416 ( 4.9%) 4 104
+ast-stats-1 - TyAlias 208 ( 2.5%) 2
+ast-stats-1 - Fn 208 ( 2.5%) 2
+ast-stats-1 GenericParam 520 ( 6.1%) 5 104
+ast-stats-1 PathSegment 720 ( 8.5%) 30 24
+ast-stats-1 Expr 832 ( 9.8%) 8 104
+ast-stats-1 - Path 104 ( 1.2%) 1
+ast-stats-1 - Match 104 ( 1.2%) 1
+ast-stats-1 - Struct 104 ( 1.2%) 1
+ast-stats-1 - Lit 208 ( 2.5%) 2
+ast-stats-1 - Block 312 ( 3.7%) 3
+ast-stats-1 Pat 840 ( 9.9%) 7 120
+ast-stats-1 - Struct 120 ( 1.4%) 1
+ast-stats-1 - Wild 120 ( 1.4%) 1
+ast-stats-1 - Ident 600 ( 7.1%) 5
+ast-stats-1 Ty 1_344 (15.9%) 14 96
+ast-stats-1 - Rptr 96 ( 1.1%) 1
+ast-stats-1 - Ptr 96 ( 1.1%) 1
+ast-stats-1 - ImplicitSelf 192 ( 2.3%) 2
+ast-stats-1 - Path 960 (11.4%) 10
+ast-stats-1 Item 1_656 (19.6%) 9 184
+ast-stats-1 - Trait 184 ( 2.2%) 1
+ast-stats-1 - Enum 184 ( 2.2%) 1
+ast-stats-1 - ForeignMod 184 ( 2.2%) 1
+ast-stats-1 - Impl 184 ( 2.2%) 1
+ast-stats-1 - Fn 368 ( 4.4%) 2
+ast-stats-1 - Use 552 ( 6.5%) 3
+ast-stats-1 ----------------------------------------------------------------
+ast-stats-1 Total 8_456
+ast-stats-1
+ast-stats-2 POST EXPANSION AST STATS
+ast-stats-2 Name Accumulated Size Count Item Size
+ast-stats-2 ----------------------------------------------------------------
+ast-stats-2 ExprField 48 ( 0.5%) 1 48
+ast-stats-2 Crate 56 ( 0.6%) 1 56
+ast-stats-2 GenericArgs 64 ( 0.7%) 1 64
+ast-stats-2 - AngleBracketed 64 ( 0.7%) 1
+ast-stats-2 Local 72 ( 0.8%) 1 72
+ast-stats-2 WherePredicate 72 ( 0.8%) 1 72
+ast-stats-2 - BoundPredicate 72 ( 0.8%) 1
+ast-stats-2 Arm 96 ( 1.0%) 2 48
+ast-stats-2 ForeignItem 96 ( 1.0%) 1 96
+ast-stats-2 - Fn 96 ( 1.0%) 1
+ast-stats-2 InlineAsm 120 ( 1.3%) 1 120
+ast-stats-2 Attribute 128 ( 1.4%) 4 32
+ast-stats-2 - DocComment 32 ( 0.3%) 1
+ast-stats-2 - Normal 96 ( 1.0%) 3
+ast-stats-2 FieldDef 160 ( 1.7%) 2 80
+ast-stats-2 Stmt 160 ( 1.7%) 5 32
+ast-stats-2 - Local 32 ( 0.3%) 1
+ast-stats-2 - Semi 32 ( 0.3%) 1
+ast-stats-2 - Expr 96 ( 1.0%) 3
+ast-stats-2 Param 160 ( 1.7%) 4 40
+ast-stats-2 FnDecl 200 ( 2.2%) 5 40
+ast-stats-2 Variant 240 ( 2.6%) 2 120
+ast-stats-2 Block 288 ( 3.1%) 6 48
+ast-stats-2 GenericBound 352 ( 3.8%) 4 88
+ast-stats-2 - Trait 352 ( 3.8%) 4
+ast-stats-2 AssocItem 416 ( 4.5%) 4 104
+ast-stats-2 - TyAlias 208 ( 2.3%) 2
+ast-stats-2 - Fn 208 ( 2.3%) 2
+ast-stats-2 GenericParam 520 ( 5.7%) 5 104
+ast-stats-2 PathSegment 792 ( 8.6%) 33 24
+ast-stats-2 Pat 840 ( 9.1%) 7 120
+ast-stats-2 - Struct 120 ( 1.3%) 1
+ast-stats-2 - Wild 120 ( 1.3%) 1
+ast-stats-2 - Ident 600 ( 6.5%) 5
+ast-stats-2 Expr 936 (10.2%) 9 104
+ast-stats-2 - Path 104 ( 1.1%) 1
+ast-stats-2 - Match 104 ( 1.1%) 1
+ast-stats-2 - Struct 104 ( 1.1%) 1
+ast-stats-2 - InlineAsm 104 ( 1.1%) 1
+ast-stats-2 - Lit 208 ( 2.3%) 2
+ast-stats-2 - Block 312 ( 3.4%) 3
+ast-stats-2 Ty 1_344 (14.6%) 14 96
+ast-stats-2 - Rptr 96 ( 1.0%) 1
+ast-stats-2 - Ptr 96 ( 1.0%) 1
+ast-stats-2 - ImplicitSelf 192 ( 2.1%) 2
+ast-stats-2 - Path 960 (10.5%) 10
+ast-stats-2 Item 2_024 (22.0%) 11 184
+ast-stats-2 - Trait 184 ( 2.0%) 1
+ast-stats-2 - Enum 184 ( 2.0%) 1
+ast-stats-2 - ExternCrate 184 ( 2.0%) 1
+ast-stats-2 - ForeignMod 184 ( 2.0%) 1
+ast-stats-2 - Impl 184 ( 2.0%) 1
+ast-stats-2 - Fn 368 ( 4.0%) 2
+ast-stats-2 - Use 736 ( 8.0%) 4
+ast-stats-2 ----------------------------------------------------------------
+ast-stats-2 Total 9_184
+ast-stats-2
+hir-stats HIR STATS
+hir-stats Name Accumulated Size Count Item Size
+hir-stats ----------------------------------------------------------------
+hir-stats ForeignItemRef 24 ( 0.2%) 1 24
+hir-stats Mod 32 ( 0.3%) 1 32
+hir-stats ExprField 40 ( 0.4%) 1 40
+hir-stats TraitItemRef 56 ( 0.5%) 2 28
+hir-stats Param 64 ( 0.6%) 2 32
+hir-stats Local 64 ( 0.6%) 1 64
+hir-stats InlineAsm 72 ( 0.7%) 1 72
+hir-stats ImplItemRef 72 ( 0.7%) 2 36
+hir-stats FieldDef 96 ( 0.9%) 2 48
+hir-stats Arm 96 ( 0.9%) 2 48
+hir-stats Body 96 ( 0.9%) 3 32
+hir-stats Stmt 96 ( 0.9%) 3 32
+hir-stats - Local 32 ( 0.3%) 1
+hir-stats - Semi 32 ( 0.3%) 1
+hir-stats - Expr 32 ( 0.3%) 1
+hir-stats FnDecl 120 ( 1.2%) 3 40
+hir-stats Attribute 128 ( 1.3%) 4 32
+hir-stats GenericArgs 144 ( 1.4%) 3 48
+hir-stats Variant 160 ( 1.6%) 2 80
+hir-stats GenericArg 160 ( 1.6%) 4 40
+hir-stats - Type 40 ( 0.4%) 1
+hir-stats - Lifetime 120 ( 1.2%) 3
+hir-stats GenericBound 192 ( 1.9%) 4 48
+hir-stats - Trait 192 ( 1.9%) 4
+hir-stats WherePredicate 216 ( 2.1%) 3 72
+hir-stats - BoundPredicate 216 ( 2.1%) 3
+hir-stats Block 288 ( 2.8%) 6 48
+hir-stats GenericParam 400 ( 3.9%) 5 80
+hir-stats Pat 440 ( 4.3%) 5 88
+hir-stats - Wild 88 ( 0.9%) 1
+hir-stats - Struct 88 ( 0.9%) 1
+hir-stats - Binding 264 ( 2.6%) 3
+hir-stats Generics 560 ( 5.5%) 10 56
+hir-stats Expr 768 ( 7.5%) 12 64
+hir-stats - Path 64 ( 0.6%) 1
+hir-stats - Struct 64 ( 0.6%) 1
+hir-stats - Match 64 ( 0.6%) 1
+hir-stats - InlineAsm 64 ( 0.6%) 1
+hir-stats - Lit 128 ( 1.3%) 2
+hir-stats - Block 384 ( 3.8%) 6
+hir-stats Item 960 ( 9.4%) 12 80
+hir-stats - Trait 80 ( 0.8%) 1
+hir-stats - Enum 80 ( 0.8%) 1
+hir-stats - ExternCrate 80 ( 0.8%) 1
+hir-stats - ForeignMod 80 ( 0.8%) 1
+hir-stats - Impl 80 ( 0.8%) 1
+hir-stats - Fn 160 ( 1.6%) 2
+hir-stats - Use 400 ( 3.9%) 5
+hir-stats Ty 1_080 (10.6%) 15 72
+hir-stats - Ptr 72 ( 0.7%) 1
+hir-stats - Rptr 72 ( 0.7%) 1
+hir-stats - Path 936 ( 9.2%) 13
+hir-stats Path 1_536 (15.1%) 32 48
+hir-stats PathSegment 2_240 (22.0%) 40 56
+hir-stats ----------------------------------------------------------------
+hir-stats Total 10_200
+hir-stats
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
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
help: provide the argument
|
LL | let _: Option<(i8,)> = Some(/* (i8,) */);
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple-errors.rs:14:34
help: provide the argument
|
LL | let _: Option<()> = Some(());
- | ~~~~~~~~
+ | ~~~~
error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple.rs:14:34
| |
| required by a bound introduced by this call
|
- = help: the trait `Future` is not implemented for `fn() -> impl Future<Output = ()> {foo}`
+ = help: the trait `Future` is not implemented for fn item `fn() -> impl Future<Output = ()> {foo}`
= note: fn() -> impl Future<Output = ()> {foo} must be a future or must implement `IntoFuture` to be awaited
note: required by a bound in `bar`
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
| |
| required by a bound introduced by this call
|
- = help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]`
+ = help: the trait `Future` is not implemented for closure `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]`
= note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33] must be a future or must implement `IntoFuture` to be awaited
note: required by a bound in `bar`
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
--- /dev/null
+// run-rustfix
+
+fn expect<T>(_: T) {}
+
+fn main() {
+ let x = Some(&());
+ expect::<Option<()>>(x.copied());
+ //~^ ERROR mismatched types
+ //~| HELP use `Option::copied` to copy the value inside the `Option`
+ let x = Ok(&());
+ expect::<Result<(), ()>>(x.copied());
+ //~^ ERROR mismatched types
+ //~| HELP use `Result::copied` to copy the value inside the `Result`
+ let s = String::new();
+ let x = Some(&s);
+ expect::<Option<String>>(x.cloned());
+ //~^ ERROR mismatched types
+ //~| HELP use `Option::cloned` to clone the value inside the `Option`
+ let x = Ok(&s);
+ expect::<Result<String, ()>>(x.cloned());
+ //~^ ERROR mismatched types
+ //~| HELP use `Result::cloned` to clone the value inside the `Result`
+}
--- /dev/null
+// run-rustfix
+
+fn expect<T>(_: T) {}
+
+fn main() {
+ let x = Some(&());
+ expect::<Option<()>>(x);
+ //~^ ERROR mismatched types
+ //~| HELP use `Option::copied` to copy the value inside the `Option`
+ let x = Ok(&());
+ expect::<Result<(), ()>>(x);
+ //~^ ERROR mismatched types
+ //~| HELP use `Result::copied` to copy the value inside the `Result`
+ let s = String::new();
+ let x = Some(&s);
+ expect::<Option<String>>(x);
+ //~^ ERROR mismatched types
+ //~| HELP use `Option::cloned` to clone the value inside the `Option`
+ let x = Ok(&s);
+ expect::<Result<String, ()>>(x);
+ //~^ ERROR mismatched types
+ //~| HELP use `Result::cloned` to clone the value inside the `Result`
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/copied-and-cloned.rs:7:26
+ |
+LL | expect::<Option<()>>(x);
+ | -------------------- ^ expected `()`, found `&()`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Option<()>`
+ found enum `Option<&()>`
+note: function defined here
+ --> $DIR/copied-and-cloned.rs:3:4
+ |
+LL | fn expect<T>(_: T) {}
+ | ^^^^^^ ----
+help: use `Option::copied` to copy the value inside the `Option`
+ |
+LL | expect::<Option<()>>(x.copied());
+ | +++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/copied-and-cloned.rs:11:30
+ |
+LL | expect::<Result<(), ()>>(x);
+ | ------------------------ ^ expected `()`, found `&()`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Result<(), ()>`
+ found enum `Result<&(), _>`
+note: function defined here
+ --> $DIR/copied-and-cloned.rs:3:4
+ |
+LL | fn expect<T>(_: T) {}
+ | ^^^^^^ ----
+help: use `Result::copied` to copy the value inside the `Result`
+ |
+LL | expect::<Result<(), ()>>(x.copied());
+ | +++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/copied-and-cloned.rs:16:30
+ |
+LL | expect::<Option<String>>(x);
+ | ------------------------ ^ expected struct `String`, found `&String`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Option<String>`
+ found enum `Option<&String>`
+note: function defined here
+ --> $DIR/copied-and-cloned.rs:3:4
+ |
+LL | fn expect<T>(_: T) {}
+ | ^^^^^^ ----
+help: use `Option::cloned` to clone the value inside the `Option`
+ |
+LL | expect::<Option<String>>(x.cloned());
+ | +++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/copied-and-cloned.rs:20:34
+ |
+LL | expect::<Result<String, ()>>(x);
+ | ---------------------------- ^ expected struct `String`, found `&String`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Result<String, ()>`
+ found enum `Result<&String, _>`
+note: function defined here
+ --> $DIR/copied-and-cloned.rs:3:4
+ |
+LL | fn expect<T>(_: T) {}
+ | ^^^^^^ ----
+help: use `Result::cloned` to clone the value inside the `Result`
+ |
+LL | expect::<Result<String, ()>>(x.cloned());
+ | +++++++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+fn main() {
+ let vec = Vec::new();
+ Vec::contains(&vec, &0);
+ //~^ ERROR no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
+ //~| HELP the function `contains` is implemented on `[_]`
+}
--- /dev/null
+error[E0599]: no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
+ --> $DIR/deref-path-method.rs:3:10
+ |
+LL | Vec::contains(&vec, &0);
+ | ^^^^^^^^ function or associated item not found in `Vec<_, _>`
+ |
+help: the function `contains` is implemented on `[_]`
+ |
+LL | <[_]>::contains(&vec, &0);
+ | ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
| --- consider calling this function
...
LL | bar(foo);
- | --- ^^^ the trait `T` is not implemented for `fn() -> impl T<O = ()> {foo}`
+ | --- ^^^ the trait `T` is not implemented for fn item `fn() -> impl T<O = ()> {foo}`
| |
| required by a bound introduced by this call
|
LL | let closure = || S;
| -- consider calling this closure
LL | bar(closure);
- | --- ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]`
+ | --- ^^^^^^^ the trait `T` is not implemented for closure `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]`
| |
| required by a bound introduced by this call
|
//! provided indirectly through an abstraction.
#![crate_type = "lib"]
+#![feature(adt_const_params)]
#![feature(transmutability)]
#![allow(dead_code, incomplete_features, non_camel_case_types)]
Src,
Dst,
Context,
- const ASSUME_ALIGNMENT: bool,
- const ASSUME_LIFETIMES: bool,
- const ASSUME_VALIDITY: bool,
- const ASSUME_VISIBILITY: bool,
+ const ASSUME: std::mem::Assume,
>()
where
Dst: BikeshedIntrinsicFrom<
Src,
Context,
- ASSUME_ALIGNMENT,
- ASSUME_LIFETIMES,
- ASSUME_VALIDITY,
- ASSUME_VISIBILITY,
+ ASSUME,
>,
{}
}
#[repr(C)] struct Src;
#[repr(C)] struct Dst;
- assert::is_transmutable::<Src, Dst, Context, false, false, false, false>();
+ assert::is_transmutable::<Src, Dst, Context, { std::mem::Assume::NOTHING }>();
}
fn via_const() {
const FALSE: bool = false;
- assert::is_transmutable::<Src, Dst, Context, FALSE, FALSE, FALSE, FALSE>();
+ assert::is_transmutable::<Src, Dst, Context, { std::mem::Assume::NOTHING }>();
}
fn via_associated_const() {
Src,
Dst,
Context,
- {Ty::FALSE},
- {Ty::FALSE},
- {Ty::FALSE},
- {Ty::FALSE}
+ {
+ std::mem::Assume {
+ alignment: {Ty::FALSE},
+ lifetimes: {Ty::FALSE},
+ safety: {Ty::FALSE},
+ validity: {Ty::FALSE},
+ }
+ }
>();
}
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn array_like<T, E, const N: usize>()
where
- T: BikeshedIntrinsicFrom<[E; N], Context, false, false, false, true>,
- [E; N]: BikeshedIntrinsicFrom<T, Context, false, false, false, true>
+ T: BikeshedIntrinsicFrom<[E; N], Context, { Assume::SAFETY }>,
+ [E; N]: BikeshedIntrinsicFrom<T, Context, { Assume::SAFETY }>
{}
}
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
{}
}
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume::ALIGNMENT
+ .and(Assume::LIFETIMES)
+ .and(Assume::SAFETY)
+ .and(Assume::VALIDITY)
+ }>
{}
}
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume::ALIGNMENT
+ .and(Assume::LIFETIMES)
+ .and(Assume::SAFETY)
+ .and(Assume::VALIDITY)
+ }>
{}
}
error[E0277]: `[String; 0]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:21:52
+ --> $DIR/should_require_well_defined_layout.rs:26:52
|
LL | assert::is_maybe_transmutable::<repr_rust, ()>();
| ^^ `[String; 0]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<[String; 0], assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<[String; 0], assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume::ALIGNMENT
+LL | | .and(Assume::LIFETIMES)
+LL | | .and(Assume::SAFETY)
+LL | | .and(Assume::VALIDITY)
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `[String; 0]` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:22:47
+ --> $DIR/should_require_well_defined_layout.rs:27:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` cannot be safely transmuted into `[String; 0]` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `[String; 0]`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[String; 0]`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume::ALIGNMENT
+LL | | .and(Assume::LIFETIMES)
+LL | | .and(Assume::SAFETY)
+LL | | .and(Assume::VALIDITY)
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `[String; 1]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:27:52
+ --> $DIR/should_require_well_defined_layout.rs:32:52
|
LL | assert::is_maybe_transmutable::<repr_rust, ()>();
| ^^ `[String; 1]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<[String; 1], assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<[String; 1], assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume::ALIGNMENT
+LL | | .and(Assume::LIFETIMES)
+LL | | .and(Assume::SAFETY)
+LL | | .and(Assume::VALIDITY)
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `[String; 1]` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:28:47
+ --> $DIR/should_require_well_defined_layout.rs:33:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` cannot be safely transmuted into `[String; 1]` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `[String; 1]`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[String; 1]`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume::ALIGNMENT
+LL | | .and(Assume::LIFETIMES)
+LL | | .and(Assume::SAFETY)
+LL | | .and(Assume::VALIDITY)
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `[String; 2]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:33:52
+ --> $DIR/should_require_well_defined_layout.rs:38:52
|
LL | assert::is_maybe_transmutable::<repr_rust, ()>();
| ^^ `[String; 2]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<[String; 2], assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<[String; 2], assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume::ALIGNMENT
+LL | | .and(Assume::LIFETIMES)
+LL | | .and(Assume::SAFETY)
+LL | | .and(Assume::VALIDITY)
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `[String; 2]` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:34:47
+ --> $DIR/should_require_well_defined_layout.rs:39:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` cannot be safely transmuted into `[String; 2]` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `[String; 2]`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[String; 2]`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume::ALIGNMENT
+LL | | .and(Assume::LIFETIMES)
+LL | | .and(Assume::SAFETY)
+LL | | .and(Assume::VALIDITY)
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error: aborting due to 6 previous errors
#![allow(dead_code)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume {
+ alignment: true,
+ lifetimes: true,
+ safety: true,
+ validity: true,
+ }
+ }>
{}
}
error[E0277]: `Zst` cannot be safely transmuted into `V0i8` in the defining scope of `n8::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:41:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:48:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ `Zst` cannot be safely transmuted into `V0i8` in the defining scope of `n8::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<Zst, n8::Context, true, true, true, true>` is not implemented for `V0i8`
+ = help: the trait `BikeshedIntrinsicFrom<Zst, n8::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0i8`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `V0i8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:43:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:50:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ `V0i8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<V0i8, n8::Context, true, true, true, true>` is not implemented for `u16`
+ = help: the trait `BikeshedIntrinsicFrom<V0i8, n8::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u16`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `Zst` cannot be safely transmuted into `V0u8` in the defining scope of `n8::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:49:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:56:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ `Zst` cannot be safely transmuted into `V0u8` in the defining scope of `n8::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<Zst, n8::Context, true, true, true, true>` is not implemented for `V0u8`
+ = help: the trait `BikeshedIntrinsicFrom<Zst, n8::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0u8`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `V0u8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:51:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:58:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ `V0u8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<V0u8, n8::Context, true, true, true, true>` is not implemented for `u16`
+ = help: the trait `BikeshedIntrinsicFrom<V0u8, n8::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u16`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `V0i16` in the defining scope of `n16::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:65:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:72:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ `u8` cannot be safely transmuted into `V0i16` in the defining scope of `n16::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, n16::Context, true, true, true, true>` is not implemented for `V0i16`
+ = help: the trait `BikeshedIntrinsicFrom<u8, n16::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0i16`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `V0i16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:67:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:74:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ `V0i16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<V0i16, n16::Context, true, true, true, true>` is not implemented for `u32`
+ = help: the trait `BikeshedIntrinsicFrom<V0i16, n16::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u32`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `V0u16` in the defining scope of `n16::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:73:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:80:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ `u8` cannot be safely transmuted into `V0u16` in the defining scope of `n16::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, n16::Context, true, true, true, true>` is not implemented for `V0u16`
+ = help: the trait `BikeshedIntrinsicFrom<u8, n16::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0u16`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `V0u16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:75:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:82:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ `V0u16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<V0u16, n16::Context, true, true, true, true>` is not implemented for `u32`
+ = help: the trait `BikeshedIntrinsicFrom<V0u16, n16::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u32`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `u16` cannot be safely transmuted into `V0i32` in the defining scope of `n32::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:89:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:96:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ `u16` cannot be safely transmuted into `V0i32` in the defining scope of `n32::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u16, n32::Context, true, true, true, true>` is not implemented for `V0i32`
+ = help: the trait `BikeshedIntrinsicFrom<u16, n32::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0i32`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `V0i32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:91:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:98:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ `V0i32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<V0i32, n32::Context, true, true, true, true>` is not implemented for `u64`
+ = help: the trait `BikeshedIntrinsicFrom<V0i32, n32::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u64`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `u16` cannot be safely transmuted into `V0u32` in the defining scope of `n32::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:97:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:104:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ `u16` cannot be safely transmuted into `V0u32` in the defining scope of `n32::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u16, n32::Context, true, true, true, true>` is not implemented for `V0u32`
+ = help: the trait `BikeshedIntrinsicFrom<u16, n32::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0u32`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `V0u32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:99:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:106:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ `V0u32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<V0u32, n32::Context, true, true, true, true>` is not implemented for `u64`
+ = help: the trait `BikeshedIntrinsicFrom<V0u32, n32::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u64`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `u32` cannot be safely transmuted into `V0i64` in the defining scope of `n64::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:113:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:120:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ `u32` cannot be safely transmuted into `V0i64` in the defining scope of `n64::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u32, n64::Context, true, true, true, true>` is not implemented for `V0i64`
+ = help: the trait `BikeshedIntrinsicFrom<u32, n64::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0i64`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `V0i64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:115:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:122:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ `V0i64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<V0i64, n64::Context, true, true, true, true>` is not implemented for `u128`
+ = help: the trait `BikeshedIntrinsicFrom<V0i64, n64::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u128`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `u32` cannot be safely transmuted into `V0u64` in the defining scope of `n64::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:121:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:128:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ `u32` cannot be safely transmuted into `V0u64` in the defining scope of `n64::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u32, n64::Context, true, true, true, true>` is not implemented for `V0u64`
+ = help: the trait `BikeshedIntrinsicFrom<u32, n64::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0u64`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `V0u64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:123:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:130:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ `V0u64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<V0u64, n64::Context, true, true, true, true>` is not implemented for `u128`
+ = help: the trait `BikeshedIntrinsicFrom<V0u64, n64::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u128`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `V0isize` in the defining scope of `nsize::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:137:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:144:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ `u8` cannot be safely transmuted into `V0isize` in the defining scope of `nsize::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, nsize::Context, true, true, true, true>` is not implemented for `V0isize`
+ = help: the trait `BikeshedIntrinsicFrom<u8, nsize::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0isize`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `V0isize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:139:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:146:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ `V0isize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<V0isize, nsize::Context, true, true, true, true>` is not implemented for `[usize; 2]`
+ = help: the trait `BikeshedIntrinsicFrom<V0isize, nsize::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[usize; 2]`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `V0usize` in the defining scope of `nsize::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:145:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:152:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ `u8` cannot be safely transmuted into `V0usize` in the defining scope of `nsize::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, nsize::Context, true, true, true, true>` is not implemented for `V0usize`
+ = help: the trait `BikeshedIntrinsicFrom<u8, nsize::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0usize`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error[E0277]: `V0usize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`.
- --> $DIR/primitive_reprs_should_have_correct_length.rs:147:44
+ --> $DIR/primitive_reprs_should_have_correct_length.rs:154:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ `V0usize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<V0usize, nsize::Context, true, true, true, true>` is not implemented for `[usize; 2]`
+ = help: the trait `BikeshedIntrinsicFrom<V0usize, nsize::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[usize; 2]`
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error: aborting due to 20 previous errors
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume {
+ alignment: true,
+ lifetimes: true,
+ safety: true,
+ validity: true,
+ }
+ }>
{}
}
error[E0277]: `void::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:21:52
+ --> $DIR/should_require_well_defined_layout.rs:28:52
|
LL | assert::is_maybe_transmutable::<repr_rust, ()>();
| ^^ `void::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<void::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<void::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `void::repr_rust` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:22:47
+ --> $DIR/should_require_well_defined_layout.rs:29:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` cannot be safely transmuted into `void::repr_rust` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `void::repr_rust`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `void::repr_rust`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `singleton::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:27:52
+ --> $DIR/should_require_well_defined_layout.rs:34:52
|
LL | assert::is_maybe_transmutable::<repr_rust, ()>();
| ^^ `singleton::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<singleton::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<singleton::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `singleton::repr_rust` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:28:47
+ --> $DIR/should_require_well_defined_layout.rs:35:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` cannot be safely transmuted into `singleton::repr_rust` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `singleton::repr_rust`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `singleton::repr_rust`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `duplex::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:33:52
+ --> $DIR/should_require_well_defined_layout.rs:40:52
|
LL | assert::is_maybe_transmutable::<repr_rust, ()>();
| ^^ `duplex::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<duplex::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<duplex::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `duplex::repr_rust` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:34:47
+ --> $DIR/should_require_well_defined_layout.rs:41:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` cannot be safely transmuted into `duplex::repr_rust` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `duplex::repr_rust`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `duplex::repr_rust`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error: aborting due to 6 previous errors
#![allow(dead_code)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume::ALIGNMENT
+ .and(Assume::LIFETIMES)
+ .and(Assume::SAFETY)
+ .and(Assume::VALIDITY)
+ }>
{}
}
#![allow(dead_code)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume::ALIGNMENT
+ .and(Assume::LIFETIMES)
+ .and(Assume::SAFETY)
+ .and(Assume::VALIDITY)
+ }>
{}
}
error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`.
- --> $DIR/should_pad_variants.rs:39:36
+ --> $DIR/should_pad_variants.rs:44:36
|
LL | assert::is_transmutable::<Src, Dst, Context>();
| ^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<Src, should_pad_variants::Context, true, true, true, true>` is not implemented for `Dst`
+ = help: the trait `BikeshedIntrinsicFrom<Src, should_pad_variants::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `Dst`
note: required by a bound in `is_transmutable`
--> $DIR/should_pad_variants.rs:13:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume::ALIGNMENT
+LL | | .and(Assume::LIFETIMES)
+LL | | .and(Assume::SAFETY)
+LL | | .and(Assume::VALIDITY)
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error: aborting due to previous error
#![allow(dead_code)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume::ALIGNMENT
+ .and(Assume::LIFETIMES)
+ .and(Assume::SAFETY)
+ .and(Assume::VALIDITY)
+ }>
{}
}
error[E0277]: `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`.
- --> $DIR/should_respect_endianness.rs:32:36
+ --> $DIR/should_respect_endianness.rs:37:36
|
LL | assert::is_transmutable::<Src, Unexpected>();
| ^^^^^^^^^^ `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<Src, assert::Context, true, true, true, true>` is not implemented for `Unexpected`
+ = help: the trait `BikeshedIntrinsicFrom<Src, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `Unexpected`
note: required by a bound in `is_transmutable`
--> $DIR/should_respect_endianness.rs:15:14
|
-LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume::ALIGNMENT
+LL | | .and(Assume::LIFETIMES)
+LL | | .and(Assume::SAFETY)
+LL | | .and(Assume::VALIDITY)
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error: aborting due to previous error
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
+ Dst: BikeshedIntrinsicFrom<Src, Context>
{}
}
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
+ Dst: BikeshedIntrinsicFrom<Src, Context>
{}
}
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
+ Dst: BikeshedIntrinsicFrom<Src, Context>
{}
}
//! provided.
#![crate_type = "lib"]
+#![feature(adt_const_params)]
+#![feature(generic_const_exprs)]
#![feature(transmutability)]
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub fn is_transmutable<
Src,
Context,
const ASSUME_ALIGNMENT: bool,
const ASSUME_LIFETIMES: bool,
+ const ASSUME_SAFETY: bool,
const ASSUME_VALIDITY: bool,
- const ASSUME_VISIBILITY: bool,
>()
where
Dst: BikeshedIntrinsicFrom<
Src,
Context,
- ASSUME_ALIGNMENT,
- ASSUME_LIFETIMES,
- ASSUME_VALIDITY,
- ASSUME_VISIBILITY,
+ { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
+ //~^ ERROR E0080
+ //~| ERROR E0080
+ //~| ERROR E0080
+ //~| ERROR E0080
>,
{}
+
+ const fn from_options(
+ alignment: bool,
+ lifetimes: bool,
+ safety: bool,
+ validity: bool,
+ ) -> Assume {
+ Assume {
+ alignment,
+ lifetimes,
+ safety,
+ validity,
+ }
+ }
}
fn test() {
error[E0308]: mismatched types
- --> $DIR/wrong-type-assume.rs:36:51
+ --> $DIR/wrong-type-assume.rs:53:51
|
LL | assert::is_transmutable::<Src, Dst, Context, {0u8}, false, false, false>();
| ^^^ expected `bool`, found `u8`
+error[E0080]: evaluation of `assert::is_transmutable::<test::Src, test::Dst, test::Context, {0u8}, false, false, false>::{constant#0}` failed
+ --> $DIR/wrong-type-assume.rs:26:15
+ |
+LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
error[E0308]: mismatched types
- --> $DIR/wrong-type-assume.rs:37:58
+ --> $DIR/wrong-type-assume.rs:54:58
|
LL | assert::is_transmutable::<Src, Dst, Context, false, {0u8}, false, false>();
| ^^^ expected `bool`, found `u8`
+error[E0080]: evaluation of `assert::is_transmutable::<test::Src, test::Dst, test::Context, false, {0u8}, false, false>::{constant#0}` failed
+ --> $DIR/wrong-type-assume.rs:26:15
+ |
+LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
error[E0308]: mismatched types
- --> $DIR/wrong-type-assume.rs:38:65
+ --> $DIR/wrong-type-assume.rs:55:65
|
LL | assert::is_transmutable::<Src, Dst, Context, false, false, {0u8}, false>();
| ^^^ expected `bool`, found `u8`
+error[E0080]: evaluation of `assert::is_transmutable::<test::Src, test::Dst, test::Context, false, false, {0u8}, false>::{constant#0}` failed
+ --> $DIR/wrong-type-assume.rs:26:15
+ |
+LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
error[E0308]: mismatched types
- --> $DIR/wrong-type-assume.rs:39:72
+ --> $DIR/wrong-type-assume.rs:56:72
|
LL | assert::is_transmutable::<Src, Dst, Context, false, false, false, {0u8}>();
| ^^^ expected `bool`, found `u8`
-error: aborting due to 4 previous errors
+error[E0080]: evaluation of `assert::is_transmutable::<test::Src, test::Dst, test::Context, false, false, false, {0u8}>::{constant#0}` failed
+ --> $DIR/wrong-type-assume.rs:26:15
+ |
+LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to 8 previous errors
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0080, E0308.
+For more information about an error, try `rustc --explain E0080`.
#![allow(incomplete_features)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
{}
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
{}
}
LL | assert::is_transmutable::<u8, bool>();
| ^^^^ `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, true>` is not implemented for `bool`
+ = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `bool`
note: required by a bound in `is_transmutable`
--> $DIR/bool.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error: aborting due to previous error
pub fn is_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
+ Dst: BikeshedIntrinsicFrom<Src, Context>
{}
}
LL | assert::is_transmutable::< i8, i16>();
| ^^^ `i8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `i16`
+ = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i16`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:63:40
LL | assert::is_transmutable::< i8, u16>();
| ^^^ `i8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `u16`
+ = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u16`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:64:40
LL | assert::is_transmutable::< i8, i32>();
| ^^^ `i8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `i32`
+ = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:65:40
LL | assert::is_transmutable::< i8, f32>();
| ^^^ `i8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `f32`
+ = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:66:40
LL | assert::is_transmutable::< i8, u32>();
| ^^^ `i8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `u32`
+ = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:67:40
LL | assert::is_transmutable::< i8, u64>();
| ^^^ `i8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `u64`
+ = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:68:40
LL | assert::is_transmutable::< i8, i64>();
| ^^^ `i8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `i64`
+ = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:69:40
LL | assert::is_transmutable::< i8, f64>();
| ^^^ `i8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `f64`
+ = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:70:39
LL | assert::is_transmutable::< i8, u128>();
| ^^^^ `i8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `u128`
+ = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:71:39
LL | assert::is_transmutable::< i8, i128>();
| ^^^^ `i8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `i128`
+ = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:73:40
LL | assert::is_transmutable::< u8, i16>();
| ^^^ `u8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `i16`
+ = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i16`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:74:40
LL | assert::is_transmutable::< u8, u16>();
| ^^^ `u8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `u16`
+ = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u16`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:75:40
LL | assert::is_transmutable::< u8, i32>();
| ^^^ `u8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `i32`
+ = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:76:40
LL | assert::is_transmutable::< u8, f32>();
| ^^^ `u8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `f32`
+ = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:77:40
LL | assert::is_transmutable::< u8, u32>();
| ^^^ `u8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `u32`
+ = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:78:40
LL | assert::is_transmutable::< u8, u64>();
| ^^^ `u8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `u64`
+ = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:79:40
LL | assert::is_transmutable::< u8, i64>();
| ^^^ `u8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `i64`
+ = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:80:40
LL | assert::is_transmutable::< u8, f64>();
| ^^^ `u8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `f64`
+ = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:81:39
LL | assert::is_transmutable::< u8, u128>();
| ^^^^ `u8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `u128`
+ = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:82:39
LL | assert::is_transmutable::< u8, i128>();
| ^^^^ `u8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `i128`
+ = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:84:40
LL | assert::is_transmutable::< i16, i32>();
| ^^^ `i16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `i32`
+ = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:85:40
LL | assert::is_transmutable::< i16, f32>();
| ^^^ `i16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `f32`
+ = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:86:40
LL | assert::is_transmutable::< i16, u32>();
| ^^^ `i16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `u32`
+ = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:87:40
LL | assert::is_transmutable::< i16, u64>();
| ^^^ `i16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `u64`
+ = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:88:40
LL | assert::is_transmutable::< i16, i64>();
| ^^^ `i16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `i64`
+ = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:89:40
LL | assert::is_transmutable::< i16, f64>();
| ^^^ `i16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `f64`
+ = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:90:39
LL | assert::is_transmutable::< i16, u128>();
| ^^^^ `i16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `u128`
+ = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:91:39
LL | assert::is_transmutable::< i16, i128>();
| ^^^^ `i16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `i128`
+ = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:93:40
LL | assert::is_transmutable::< u16, i32>();
| ^^^ `u16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `i32`
+ = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:94:40
LL | assert::is_transmutable::< u16, f32>();
| ^^^ `u16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `f32`
+ = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:95:40
LL | assert::is_transmutable::< u16, u32>();
| ^^^ `u16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `u32`
+ = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:96:40
LL | assert::is_transmutable::< u16, u64>();
| ^^^ `u16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `u64`
+ = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:97:40
LL | assert::is_transmutable::< u16, i64>();
| ^^^ `u16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `i64`
+ = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:98:40
LL | assert::is_transmutable::< u16, f64>();
| ^^^ `u16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `f64`
+ = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:99:39
LL | assert::is_transmutable::< u16, u128>();
| ^^^^ `u16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `u128`
+ = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:100:39
LL | assert::is_transmutable::< u16, i128>();
| ^^^^ `u16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `i128`
+ = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:102:40
LL | assert::is_transmutable::< i32, u64>();
| ^^^ `i32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, false, false, false, false>` is not implemented for `u64`
+ = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:103:40
LL | assert::is_transmutable::< i32, i64>();
| ^^^ `i32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, false, false, false, false>` is not implemented for `i64`
+ = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:104:40
LL | assert::is_transmutable::< i32, f64>();
| ^^^ `i32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, false, false, false, false>` is not implemented for `f64`
+ = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:105:39
LL | assert::is_transmutable::< i32, u128>();
| ^^^^ `i32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, false, false, false, false>` is not implemented for `u128`
+ = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:106:39
LL | assert::is_transmutable::< i32, i128>();
| ^^^^ `i32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, false, false, false, false>` is not implemented for `i128`
+ = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `f32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:108:40
LL | assert::is_transmutable::< f32, u64>();
| ^^^ `f32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, false, false, false, false>` is not implemented for `u64`
+ = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `f32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:109:40
LL | assert::is_transmutable::< f32, i64>();
| ^^^ `f32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, false, false, false, false>` is not implemented for `i64`
+ = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `f32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:110:40
LL | assert::is_transmutable::< f32, f64>();
| ^^^ `f32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, false, false, false, false>` is not implemented for `f64`
+ = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `f32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:111:39
LL | assert::is_transmutable::< f32, u128>();
| ^^^^ `f32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, false, false, false, false>` is not implemented for `u128`
+ = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `f32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:112:39
LL | assert::is_transmutable::< f32, i128>();
| ^^^^ `f32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, false, false, false, false>` is not implemented for `i128`
+ = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:114:40
LL | assert::is_transmutable::< u32, u64>();
| ^^^ `u32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, false, false, false, false>` is not implemented for `u64`
+ = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:115:40
LL | assert::is_transmutable::< u32, i64>();
| ^^^ `u32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, false, false, false, false>` is not implemented for `i64`
+ = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:116:40
LL | assert::is_transmutable::< u32, f64>();
| ^^^ `u32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, false, false, false, false>` is not implemented for `f64`
+ = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:117:39
LL | assert::is_transmutable::< u32, u128>();
| ^^^^ `u32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, false, false, false, false>` is not implemented for `u128`
+ = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:118:39
LL | assert::is_transmutable::< u32, i128>();
| ^^^^ `u32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, false, false, false, false>` is not implemented for `i128`
+ = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:120:39
LL | assert::is_transmutable::< u64, u128>();
| ^^^^ `u64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, false, false, false, false>` is not implemented for `u128`
+ = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `u64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:121:39
LL | assert::is_transmutable::< u64, i128>();
| ^^^^ `u64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, false, false, false, false>` is not implemented for `i128`
+ = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:123:39
LL | assert::is_transmutable::< i64, u128>();
| ^^^^ `i64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, false, false, false, false>` is not implemented for `u128`
+ = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `i64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:124:39
LL | assert::is_transmutable::< i64, i128>();
| ^^^^ `i64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, false, false, false, false>` is not implemented for `i128`
+ = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `f64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:126:39
LL | assert::is_transmutable::< f64, u128>();
| ^^^^ `f64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, false, false, false, false>` is not implemented for `u128`
+ = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `f64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
--> $DIR/numbers.rs:127:39
LL | assert::is_transmutable::< f64, i128>();
| ^^^^ `f64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, false, false, false, false>` is not implemented for `i128`
+ = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error: aborting due to 57 previous errors
#![allow(dead_code)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume::ALIGNMENT
+ .and(Assume::LIFETIMES)
+ .and(Assume::SAFETY)
+ .and(Assume::VALIDITY)
+ }>
{}
}
error[E0277]: `()` cannot be safely transmuted into `u8` in the defining scope of `should_have_correct_size::Context`.
- --> $DIR/unit.rs:23:35
+ --> $DIR/unit.rs:28:35
|
LL | assert::is_transmutable::<(), u8, Context>();
| ^^ `()` cannot be safely transmuted into `u8` in the defining scope of `should_have_correct_size::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<(), should_have_correct_size::Context, true, true, true, true>` is not implemented for `u8`
+ = help: the trait `BikeshedIntrinsicFrom<(), should_have_correct_size::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u8`
note: required by a bound in `is_transmutable`
--> $DIR/unit.rs:12:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume::ALIGNMENT
+LL | | .and(Assume::LIFETIMES)
+LL | | .and(Assume::SAFETY)
+LL | | .and(Assume::VALIDITY)
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error: aborting due to previous error
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume {
+ alignment: true,
+ lifetimes: true,
+ safety: true,
+ validity: true,
+ }
+ }>
{}
}
error[E0277]: `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
- --> $DIR/references.rs:19:52
+ --> $DIR/references.rs:26:52
|
LL | assert::is_maybe_transmutable::<&'static Unit, &'static Unit>();
| ^^^^^^^^^^^^^ `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<&'static Unit, assert::Context, true, true, true, true>` is not implemented for `&'static Unit`
+ = help: the trait `BikeshedIntrinsicFrom<&'static Unit, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `&'static Unit`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/references.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error: aborting due to previous error
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume {
+ alignment: true,
+ lifetimes: true,
+ safety: true,
+ validity: true,
+ }
+ }>
{}
}
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume {
+ alignment: true,
+ lifetimes: true,
+ safety: true,
+ validity: true,
+ }
+ }>
{}
}
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume {
+ alignment: true,
+ lifetimes: true,
+ safety: true,
+ validity: true,
+ }
+ }>
{}
}
error[E0277]: `should_reject_repr_rust::unit::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:21:52
+ --> $DIR/should_require_well_defined_layout.rs:28:52
|
LL | assert::is_maybe_transmutable::<repr_rust, ()>();
| ^^ `should_reject_repr_rust::unit::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::unit::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::unit::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::unit::repr_rust` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:22:47
+ --> $DIR/should_require_well_defined_layout.rs:29:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::unit::repr_rust` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `should_reject_repr_rust::unit::repr_rust`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `should_reject_repr_rust::unit::repr_rust`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `should_reject_repr_rust::tuple::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:27:52
+ --> $DIR/should_require_well_defined_layout.rs:34:52
|
LL | assert::is_maybe_transmutable::<repr_rust, ()>();
| ^^ `should_reject_repr_rust::tuple::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::tuple::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::tuple::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::tuple::repr_rust` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:28:47
+ --> $DIR/should_require_well_defined_layout.rs:35:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::tuple::repr_rust` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `should_reject_repr_rust::tuple::repr_rust`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `should_reject_repr_rust::tuple::repr_rust`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `should_reject_repr_rust::braces::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:33:52
+ --> $DIR/should_require_well_defined_layout.rs:40:52
|
LL | assert::is_maybe_transmutable::<repr_rust, ()>();
| ^^ `should_reject_repr_rust::braces::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::braces::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::braces::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::braces::repr_rust` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:34:47
+ --> $DIR/should_require_well_defined_layout.rs:41:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::braces::repr_rust` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `should_reject_repr_rust::braces::repr_rust`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `should_reject_repr_rust::braces::repr_rust`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `aligned::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:39:52
+ --> $DIR/should_require_well_defined_layout.rs:46:52
|
LL | assert::is_maybe_transmutable::<repr_rust, ()>();
| ^^ `aligned::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<aligned::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<aligned::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `aligned::repr_rust` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:40:47
+ --> $DIR/should_require_well_defined_layout.rs:47:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` cannot be safely transmuted into `aligned::repr_rust` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `aligned::repr_rust`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `aligned::repr_rust`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `packed::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:45:52
+ --> $DIR/should_require_well_defined_layout.rs:52:52
|
LL | assert::is_maybe_transmutable::<repr_rust, ()>();
| ^^ `packed::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<packed::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<packed::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `packed::repr_rust` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:46:47
+ --> $DIR/should_require_well_defined_layout.rs:53:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` cannot be safely transmuted into `packed::repr_rust` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `packed::repr_rust`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `packed::repr_rust`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `nested::repr_c` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:52:49
+ --> $DIR/should_require_well_defined_layout.rs:59:49
|
LL | assert::is_maybe_transmutable::<repr_c, ()>();
| ^^ `nested::repr_c` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<nested::repr_c, assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<nested::repr_c, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `nested::repr_c` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:53:47
+ --> $DIR/should_require_well_defined_layout.rs:60:47
|
LL | assert::is_maybe_transmutable::<u128, repr_c>();
| ^^^^^^ `u128` cannot be safely transmuted into `nested::repr_c` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `nested::repr_c`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `nested::repr_c`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error: aborting due to 12 previous errors
#![allow(dead_code)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume::ALIGNMENT
+ .and(Assume::LIFETIMES)
+ .and(Assume::SAFETY)
+ .and(Assume::VALIDITY)
+ }>
{}
}
#![allow(incomplete_features)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
{}
}
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume {
+ alignment: true,
+ lifetimes: true,
+ safety: true,
+ validity: true,
+ }
+ }>
{}
}
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume {
+ alignment: true,
+ lifetimes: true,
+ safety: true,
+ validity: true,
+ }
+ }>
{}
}
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume {
+ alignment: true,
+ lifetimes: true,
+ safety: true,
+ validity: true,
+ }
+ }>
{}
}
error[E0277]: `should_reject_repr_rust::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:23:48
+ --> $DIR/should_require_well_defined_layout.rs:30:48
|
LL | assert::is_maybe_transmutable::<repr_rust, ()>();
| ^^ `should_reject_repr_rust::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+ = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::repr_rust` in the defining scope of `assert::Context`.
- --> $DIR/should_require_well_defined_layout.rs:24:43
+ --> $DIR/should_require_well_defined_layout.rs:31:43
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::repr_rust` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `should_reject_repr_rust::repr_rust`
+ = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `should_reject_repr_rust::repr_rust`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
-LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | pub fn is_maybe_transmutable<Src, Dst>()
+ | --------------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume {
+LL | | alignment: true,
+LL | | lifetimes: true,
+... |
+LL | | }
+LL | | }>
+ | |__________^ required by this bound in `is_maybe_transmutable`
error: aborting due to 2 previous errors
#![allow(dead_code)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, {
+ Assume::ALIGNMENT
+ .and(Assume::LIFETIMES)
+ .and(Assume::SAFETY)
+ .and(Assume::VALIDITY)
+ }>
{}
}
error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`.
- --> $DIR/should_pad_variants.rs:39:36
+ --> $DIR/should_pad_variants.rs:44:36
|
LL | assert::is_transmutable::<Src, Dst, Context>();
| ^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<Src, should_pad_variants::Context, true, true, true, true>` is not implemented for `Dst`
+ = help: the trait `BikeshedIntrinsicFrom<Src, should_pad_variants::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `Dst`
note: required by a bound in `is_transmutable`
--> $DIR/should_pad_variants.rs:13:14
|
-LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
-LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | pub fn is_transmutable<Src, Dst, Context>()
+ | --------------- required by a bound in this
+LL | where
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
+ | ______________^
+LL | | Assume::ALIGNMENT
+LL | | .and(Assume::LIFETIMES)
+LL | | .and(Assume::SAFETY)
+LL | | .and(Assume::VALIDITY)
+LL | | }>
+ | |__________^ required by this bound in `is_transmutable`
error: aborting due to previous error
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, true, true>
- // validity IS assumed --------------------------------^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
{}
}
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
{}
}
LL | assert::is_transmutable::<Superset, Subset>();
| ^^^^^^ `Superset` cannot be safely transmuted into `Subset` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<Superset, assert::Context, false, false, false, true>` is not implemented for `Subset`
+ = help: the trait `BikeshedIntrinsicFrom<Superset, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `Subset`
note: required by a bound in `is_transmutable`
--> $DIR/should_reject_contraction.rs:13:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error: aborting due to previous error
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_maybe_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, true, true>
- // validity IS assumed --------------------------------^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
{}
}
error[E0277]: `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`.
- --> $DIR/should_reject_disjoint.rs:34:40
+ --> $DIR/should_reject_disjoint.rs:33:40
|
LL | assert::is_maybe_transmutable::<A, B>();
| ^ `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<A, assert::Context, false, false, true, true>` is not implemented for `B`
+ = help: the trait `BikeshedIntrinsicFrom<A, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: true }>` is not implemented for `B`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_reject_disjoint.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
| --------------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`.
- --> $DIR/should_reject_disjoint.rs:35:40
+ --> $DIR/should_reject_disjoint.rs:34:40
|
LL | assert::is_maybe_transmutable::<B, A>();
| ^ `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<B, assert::Context, false, false, true, true>` is not implemented for `A`
+ = help: the trait `BikeshedIntrinsicFrom<B, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: true }>` is not implemented for `A`
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_reject_disjoint.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
| --------------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, true, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
error: aborting due to 2 previous errors
#![allow(dead_code, incomplete_features, non_camel_case_types)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
pub fn is_transmutable<Src, Dst>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
- // validity is NOT assumed ----------------------------^^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+ // validity is NOT assumed --------------^^^^^^^^^^^^^^^^^^
{}
}
LL | assert::is_transmutable::<A, B>();
| ^ `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<A, assert::Context, false, false, false, true>` is not implemented for `B`
+ = help: the trait `BikeshedIntrinsicFrom<A, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `B`
note: required by a bound in `is_transmutable`
--> $DIR/should_reject_intersecting.rs:14:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`.
--> $DIR/should_reject_intersecting.rs:37:34
LL | assert::is_transmutable::<B, A>();
| ^ `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<B, assert::Context, false, false, false, true>` is not implemented for `A`
+ = help: the trait `BikeshedIntrinsicFrom<B, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `A`
note: required by a bound in `is_transmutable`
--> $DIR/should_reject_intersecting.rs:14:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error: aborting due to 2 previous errors
#![allow(dead_code)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
- // visibility IS assumed -------------------------------------^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+ // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^
{}
}
#![allow(dead_code)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
- // visibility IS assumed -------------------------------------^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+ // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^
{}
}
#![allow(dead_code)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
- // visibility IS assumed -------------------------------------^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+ // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^
{}
}
#![allow(dead_code)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
- // visibility IS assumed -------------------------------------^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+ // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^
{}
}
#![allow(dead_code)]
mod assert {
- use std::mem::BikeshedIntrinsicFrom;
+ use std::mem::{Assume, BikeshedIntrinsicFrom};
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
- // visibility IS assumed -------------------------------------^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+ // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^
{}
}
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- // visibility is NOT assumed ---------------------------------^^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
{}
}
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- // visibility is NOT assumed ---------------------------------^^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
{}
}
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- // visibility is NOT assumed ---------------------------------^^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
{}
}
error[E0446]: private type `src::Zst` in public interface
- --> $DIR/should_accept_if_src_has_unreachable_field.rs:23:9
+ --> $DIR/should_accept_if_src_has_unreachable_field.rs:22:9
|
LL | #[repr(C)] pub(self) struct Zst; // <- unreachable type
| -------------------- `src::Zst` declared as private
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- // visibility is NOT assumed ---------------------------------^^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
{}
}
error[E0603]: struct `Src` is private
- --> $DIR/should_accept_if_src_has_unreachable_ty.rs:38:36
+ --> $DIR/should_accept_if_src_has_unreachable_ty.rs:37:36
|
LL | assert::is_transmutable::<src::Src, dst::Dst, Context>();
| ^^^ private struct
|
note: the struct `Src` is defined here
- --> $DIR/should_accept_if_src_has_unreachable_ty.rs:23:16
+ --> $DIR/should_accept_if_src_has_unreachable_ty.rs:22:16
|
LL | #[repr(C)] pub(self) struct Src {
| ^^^^^^^^^^^^^^^^^^^^
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- // visibility is NOT assumed ---------------------------------^^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
{}
}
error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
- --> $DIR/should_reject_if_dst_has_private_field.rs:36:41
+ --> $DIR/should_reject_if_dst_has_private_field.rs:35:41
|
LL | assert::is_transmutable::<src::Src, dst::Dst, Context>();
| ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, false, false, false, false>` is not implemented for `Dst`
+ = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `Dst`
note: required by a bound in `is_transmutable`
--> $DIR/should_reject_if_dst_has_private_field.rs:13:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error: aborting due to previous error
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- // visibility is NOT assumed ---------------------------------^^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
{}
}
error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
- --> $DIR/should_reject_if_dst_has_private_variant.rs:37:41
+ --> $DIR/should_reject_if_dst_has_private_variant.rs:36:41
|
LL | assert::is_transmutable::<src::Src, dst::Dst, Context>();
| ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, false, false, false, false>` is not implemented for `Dst`
+ = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `Dst`
note: required by a bound in `is_transmutable`
--> $DIR/should_reject_if_dst_has_private_variant.rs:13:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error: aborting due to previous error
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- // visibility is NOT assumed ---------------------------------^^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
{}
}
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- // visibility is NOT assumed ---------------------------------^^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
{}
}
error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
- --> $DIR/should_reject_if_dst_has_unreachable_field.rs:38:41
+ --> $DIR/should_reject_if_dst_has_unreachable_field.rs:37:41
|
LL | assert::is_transmutable::<src::Src, dst::Dst, Context>();
| ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, false, false, false, false>` is not implemented for `Dst`
+ = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `Dst`
note: required by a bound in `is_transmutable`
--> $DIR/should_reject_if_dst_has_unreachable_field.rs:15:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error: aborting due to previous error
pub fn is_transmutable<Src, Dst, Context>()
where
- Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- // visibility is NOT assumed ---------------------------------^^^^^
+ Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
{}
}
error[E0603]: struct `Dst` is private
- --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:39:46
+ --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:38:46
|
LL | assert::is_transmutable::<src::Src, dst::Dst, Context>();
| ^^^ private struct
|
note: the struct `Dst` is defined here
- --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:32:16
+ --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:31:16
|
LL | #[repr(C)] pub(self) struct Dst {
| ^^^^^^^^^^^^^^^^^^^^
error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
- --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:39:41
+ --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:38:41
|
LL | assert::is_transmutable::<src::Src, dst::Dst, Context>();
| ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
|
- = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, false, false, false, false>` is not implemented for `Dst`
+ = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `Dst`
note: required by a bound in `is_transmutable`
--> $DIR/should_reject_if_dst_has_unreachable_ty.rs:15:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
| --------------- required by a bound in this
LL | where
-LL | Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL | Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
error: aborting due to 2 previous errors
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
--> $DIR/bad-interconversion.rs:11:12
|
-LL | / fn option_to_result() -> Result<u64, String> {
-LL | | Some(3)?;
- | | ^ use `.ok_or(...)?` to provide an error compatible with `Result<u64, String>`
-LL | |
-LL | | Ok(10)
-LL | | }
- | |_- this function returns a `Result`
+LL | fn option_to_result() -> Result<u64, String> {
+ | -------------------------------------------- this function returns a `Result`
+LL | Some(3)?;
+ | ^ use `.ok_or(...)?` to provide an error compatible with `Result<u64, String>`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>`
= help: the following other types implement trait `FromResidual<R>`:
error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result`
--> $DIR/bad-interconversion.rs:17:31
|
-LL | / fn control_flow_to_result() -> Result<u64, String> {
-LL | | Ok(ControlFlow::Break(123)?)
- | | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result<u64, String>`
-LL | |
-LL | | }
- | |_- this function returns a `Result`
+LL | fn control_flow_to_result() -> Result<u64, String> {
+ | -------------------------------------------------- this function returns a `Result`
+LL | Ok(ControlFlow::Break(123)?)
+ | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result<u64, String>`
|
= help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>`
= help: the following other types implement trait `FromResidual<R>`:
error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
--> $DIR/bad-interconversion.rs:22:22
|
-LL | / fn result_to_option() -> Option<u16> {
-LL | | Some(Err("hello")?)
- | | ^ use `.ok()?` if you want to discard the `Result<Infallible, &str>` error information
-LL | |
-LL | | }
- | |_- this function returns an `Option`
+LL | fn result_to_option() -> Option<u16> {
+ | ------------------------------------ this function returns an `Option`
+LL | Some(Err("hello")?)
+ | ^ use `.ok()?` if you want to discard the `Result<Infallible, &str>` error information
|
= help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `Option<u16>`
= help: the following other types implement trait `FromResidual<R>`:
error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
--> $DIR/bad-interconversion.rs:27:33
|
-LL | / fn control_flow_to_option() -> Option<u64> {
-LL | | Some(ControlFlow::Break(123)?)
- | | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option<u64>`
-LL | |
-LL | | }
- | |_- this function returns an `Option`
+LL | fn control_flow_to_option() -> Option<u64> {
+ | ------------------------------------------ this function returns an `Option`
+LL | Some(ControlFlow::Break(123)?)
+ | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option<u64>`
|
= help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Option<u64>`
= help: the following other types implement trait `FromResidual<R>`:
error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
--> $DIR/bad-interconversion.rs:32:39
|
-LL | / fn result_to_control_flow() -> ControlFlow<String> {
-LL | | ControlFlow::Continue(Err("hello")?)
- | | ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `ControlFlow<String>`
-LL | |
-LL | | }
- | |_- this function returns a `ControlFlow`
+LL | fn result_to_control_flow() -> ControlFlow<String> {
+ | -------------------------------------------------- this function returns a `ControlFlow`
+LL | ControlFlow::Continue(Err("hello")?)
+ | ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `ControlFlow<String>`
|
= help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>`
= help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
--> $DIR/bad-interconversion.rs:37:12
|
-LL | / fn option_to_control_flow() -> ControlFlow<u64> {
-LL | | Some(3)?;
- | | ^ this `?` produces `Option<Infallible>`, which is incompatible with `ControlFlow<u64>`
-LL | |
-LL | | ControlFlow::Break(10)
-LL | | }
- | |_- this function returns a `ControlFlow`
+LL | fn option_to_control_flow() -> ControlFlow<u64> {
+ | ----------------------------------------------- this function returns a `ControlFlow`
+LL | Some(3)?;
+ | ^ this `?` produces `Option<Infallible>`, which is incompatible with `ControlFlow<u64>`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>`
= help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
error[E0277]: the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s (with the same Break type)
--> $DIR/bad-interconversion.rs:43:29
|
-LL | / fn control_flow_to_control_flow() -> ControlFlow<i64> {
-LL | | ControlFlow::Break(4_u8)?;
- | | ^ this `?` produces `ControlFlow<u8, Infallible>`, which is incompatible with `ControlFlow<i64>`
-LL | |
-LL | | ControlFlow::Continue(())
-LL | | }
- | |_- this function returns a `ControlFlow`
+LL | fn control_flow_to_control_flow() -> ControlFlow<i64> {
+ | ----------------------------------------------------- this function returns a `ControlFlow`
+LL | ControlFlow::Break(4_u8)?;
+ | ^ this `?` produces `ControlFlow<u8, Infallible>`, which is incompatible with `ControlFlow<i64>`
|
= help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>`
= note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
--> $DIR/option-to-result.rs:5:6
|
-LL | / fn test_result() -> Result<(),()> {
-LL | | let a:Option<()> = Some(());
-LL | | a?;
- | | ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>`
-LL | | Ok(())
-LL | | }
- | |_- this function returns a `Result`
+LL | fn test_result() -> Result<(),()> {
+ | --------------------------------- this function returns a `Result`
+LL | let a:Option<()> = Some(());
+LL | a?;
+ | ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>`
= help: the following other types implement trait `FromResidual<R>`:
error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
--> $DIR/option-to-result.rs:11:6
|
-LL | / fn test_option() -> Option<i32>{
-LL | | let a:Result<i32, i32> = Ok(5);
-LL | | a?;
- | | ^ use `.ok()?` if you want to discard the `Result<Infallible, i32>` error information
-LL | | Some(5)
-LL | | }
- | |_- this function returns an `Option`
+LL | fn test_option() -> Option<i32>{
+ | ------------------------------- this function returns an `Option`
+LL | let a:Result<i32, i32> = Ok(5);
+LL | a?;
+ | ^ use `.ok()?` if you want to discard the `Result<Infallible, i32>` error information
|
= help: the trait `FromResidual<Result<Infallible, i32>>` is not implemented for `Option<i32>`
= help: the following other types implement trait `FromResidual<R>`:
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> $DIR/try-on-option-diagnostics.rs:7:6
|
-LL | / fn a_function() -> u32 {
-LL | | let x: Option<u32> = None;
-LL | | x?;
- | | ^ cannot use the `?` operator in a function that returns `u32`
-LL | | 22
-LL | | }
- | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn a_function() -> u32 {
+ | ---------------------- this function should return `Result` or `Option` to accept `?`
+LL | let x: Option<u32> = None;
+LL | x?;
+ | ^ cannot use the `?` operator in a function that returns `u32`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> $DIR/try-on-option-diagnostics.rs:14:10
|
-LL | let a_closure = || {
- | _____________________-
-LL | | let x: Option<u32> = None;
-LL | | x?;
- | | ^ cannot use the `?` operator in a closure that returns `{integer}`
-LL | | 22
-LL | | };
- | |_____- this function should return `Result` or `Option` to accept `?`
+LL | let a_closure = || {
+ | -- this function should return `Result` or `Option` to accept `?`
+LL | let x: Option<u32> = None;
+LL | x?;
+ | ^ cannot use the `?` operator in a closure that returns `{integer}`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> $DIR/try-on-option-diagnostics.rs:26:14
|
-LL | / fn a_method() {
-LL | | let x: Option<u32> = None;
-LL | | x?;
- | | ^ cannot use the `?` operator in a method that returns `()`
-LL | | }
- | |_________- this function should return `Result` or `Option` to accept `?`
+LL | fn a_method() {
+ | ------------- this function should return `Result` or `Option` to accept `?`
+LL | let x: Option<u32> = None;
+LL | x?;
+ | ^ cannot use the `?` operator in a method that returns `()`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> $DIR/try-on-option-diagnostics.rs:39:14
|
-LL | / fn a_trait_method() {
-LL | | let x: Option<u32> = None;
-LL | | x?;
- | | ^ cannot use the `?` operator in a trait method that returns `()`
-LL | | }
- | |_________- this function should return `Result` or `Option` to accept `?`
+LL | fn a_trait_method() {
+ | ------------------- this function should return `Result` or `Option` to accept `?`
+LL | let x: Option<u32> = None;
+LL | x?;
+ | ^ cannot use the `?` operator in a trait method that returns `()`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
--> $DIR/try-on-option.rs:5:6
|
-LL | / fn foo() -> Result<u32, ()> {
-LL | | let x: Option<u32> = None;
-LL | | x?;
- | | ^ use `.ok_or(...)?` to provide an error compatible with `Result<u32, ()>`
-LL | | Ok(22)
-LL | | }
- | |_- this function returns a `Result`
+LL | fn foo() -> Result<u32, ()> {
+ | --------------------------- this function returns a `Result`
+LL | let x: Option<u32> = None;
+LL | x?;
+ | ^ use `.ok_or(...)?` to provide an error compatible with `Result<u32, ()>`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>`
= help: the following other types implement trait `FromResidual<R>`:
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> $DIR/try-on-option.rs:11:6
|
-LL | / fn bar() -> u32 {
-LL | | let x: Option<u32> = None;
-LL | | x?;
- | | ^ cannot use the `?` operator in a function that returns `u32`
-LL | | 22
-LL | | }
- | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn bar() -> u32 {
+ | --------------- this function should return `Result` or `Option` to accept `?`
+LL | let x: Option<u32> = None;
+LL | x?;
+ | ^ cannot use the `?` operator in a function that returns `u32`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> $DIR/try-operator-on-main.rs:7:31
|
-LL | / fn main() {
-LL | | // error for a `Try` type on a non-`Try` fn
-LL | | std::fs::File::open("foo")?;
- | | ^ cannot use the `?` operator in a function that returns `()`
-LL | |
-... |
-LL | | try_trait_generic::<()>();
-LL | | }
- | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn main() {
+ | --------- this function should return `Result` or `Option` to accept `?`
+LL | // error for a `Try` type on a non-`Try` fn
+LL | std::fs::File::open("foo")?;
+ | ^ cannot use the `?` operator in a function that returns `()`
|
= help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> $DIR/try-operator-on-main.rs:10:7
|
-LL | / fn main() {
-LL | | // error for a `Try` type on a non-`Try` fn
-LL | | std::fs::File::open("foo")?;
-LL | |
-LL | | // a non-`Try` type on a non-`Try` fn
-LL | | ()?;
- | | ^ cannot use the `?` operator in a function that returns `()`
-... |
-LL | | try_trait_generic::<()>();
-LL | | }
- | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn main() {
+ | --------- this function should return `Result` or `Option` to accept `?`
+...
+LL | ()?;
+ | ^ cannot use the `?` operator in a function that returns `()`
|
= help: the trait `FromResidual<_>` is not implemented for `()`
help: remove the extra argument
|
LL | groups.push(/* (Vec<String>, Vec<Process>) */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: remove the extra argument
|
LL | (|| {})();
- | ~~~~~~~~~
+ | ~~
error: aborting due to previous error
help: provide the argument
|
LL | <E>::V(/* u8 */);
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
help: remove the extra argument
|
LL | let x: Vec::with_capacity(10);
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~
error: aborting due to 2 previous errors
--- /dev/null
+// issue #101376
+
+use std::ops::AddAssign;
+struct Foo;
+
+impl AddAssign<()> for Foo {
+ fn add_assign(&mut self, _: ()) {}
+}
+
+impl AddAssign<()> for &mut Foo {
+ fn add_assign(&mut self, _: ()) {}
+}
+
+fn main() {
+ (&mut Foo) += ();
+ //~^ ERROR invalid left-hand side of assignment
+ //~| NOTE cannot assign to this expression
+ //~| HELP consider dereferencing the left-hand side of this operation
+}
--- /dev/null
+error[E0067]: invalid left-hand side of assignment
+ --> $DIR/assign-non-lval-needs-deref.rs:15:16
+ |
+LL | (&mut Foo) += ();
+ | ---------- ^^
+ | |
+ | cannot assign to this expression
+ |
+help: consider dereferencing the left-hand side of this operation
+ |
+LL | *(&mut Foo) += ();
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0067`.
--- /dev/null
+fn foo<T: std::fmt::Display>() {}
+
+fn main() {
+ let x = foo::<()>;
+ //~^ ERROR `()` doesn't implement `std::fmt::Display`
+}
--- /dev/null
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+ --> $DIR/point-at-type-param-in-path-expr.rs:4:19
+ |
+LL | let x = foo::<()>;
+ | ^^ `()` cannot be formatted with the default formatter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `()`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+note: required by a bound in `foo`
+ --> $DIR/point-at-type-param-in-path-expr.rs:1:11
+ |
+LL | fn foo<T: std::fmt::Display>() {}
+ | ^^^^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
help: remove the extra argument
|
LL | l(vec![])
- |
+ | ~~~~~~~~
error: aborting due to previous error
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
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
help: provide the argument
|
LL | let _ = Ok(/* value */);
- | ~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0061]: this struct takes 1 argument but 0 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:9:13
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
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
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
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
help: remove the extra argument
|
LL | let _ = DoubleWrapper(5, 2);
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~
error: aborting due to 8 previous errors
fn main() {
<i32 as Add<u32>>::add(1, 2);
//~^ ERROR cannot add `u32` to `i32`
+ //~| ERROR cannot add `u32` to `i32`
<i32 as Add<i32>>::add(1u32, 2);
//~^ ERROR mismatched types
<i32 as Add<i32>>::add(1, 2u32);
and 48 others
error[E0308]: mismatched types
- --> $DIR/ufcs-qpath-self-mismatch.rs:6:28
+ --> $DIR/ufcs-qpath-self-mismatch.rs:7:28
|
LL | <i32 as Add<i32>>::add(1u32, 2);
| ---------------------- ^^^^ expected `i32`, found `u32`
| ~~~
error[E0308]: mismatched types
- --> $DIR/ufcs-qpath-self-mismatch.rs:8:31
+ --> $DIR/ufcs-qpath-self-mismatch.rs:9:31
|
LL | <i32 as Add<i32>>::add(1, 2u32);
| ---------------------- ^^^^ expected `i32`, found `u32`
LL | <i32 as Add<i32>>::add(1, 2i32);
| ~~~
-error: aborting due to 3 previous errors
+error[E0277]: cannot add `u32` to `i32`
+ --> $DIR/ufcs-qpath-self-mismatch.rs:4:5
+ |
+LL | <i32 as Add<u32>>::add(1, 2);
+ | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32`
+ |
+ = help: the trait `Add<u32>` is not implemented for `i32`
+ = help: the following other types implement trait `Add<Rhs>`:
+ <&'a f32 as Add<f32>>
+ <&'a f64 as Add<f64>>
+ <&'a i128 as Add<i128>>
+ <&'a i16 as Add<i16>>
+ <&'a i32 as Add<i32>>
+ <&'a i64 as Add<i64>>
+ <&'a i8 as Add<i8>>
+ <&'a isize as Add<isize>>
+ and 48 others
+
+error: aborting due to 4 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it_mut`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it_once`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-wrong-abi.rs:9:15
|
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
note: required by a bound in `call_it_mut`
--> $DIR/unboxed-closures-wrong-abi.rs:12:19
|
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
note: required by a bound in `call_it_once`
--> $DIR/unboxed-closures-wrong-abi.rs:15:20
|
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+ = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+ = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it_mut`
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+ = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it_once`
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20
| ^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
+ = note: all function arguments must have a statically known size
= help: unsized fn params are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
- |
-LL | &X(&*Y)
- | +
error: aborting due to previous error
-Subproject commit 4ed54cecce3ce9ab6ff058781f4c8a500ee6b8b5
+Subproject commit 646e9a0b9ea8354cc409d05f10e8dc752c5de78e
impl<'tcx> LateLintPass<'tcx> for MyStructLint {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
// Check our expr is calling a method
- if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..]) = &expr.kind
+ if let hir::ExprKind::MethodCall(path, _, _self_arg, ..) = &expr.kind
// Check the name of this method is `some_method`
&& path.ident.name == sym!(some_method)
// Optionally, check the type of the self argument.
&& matches!(cx.tcx.get_diagnostic_name(macro_call.def_id), Some(sym::assert_macro))
&& let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn)
&& matches!(panic_expn, PanicExpn::Empty)
- && let ExprKind::MethodCall(method_segment, [recv], _) = condition.kind
+ && let ExprKind::MethodCall(method_segment, recv, [], _) = condition.kind
&& let result_type_with_refs = cx.typeck_results().expr_ty(recv)
&& let result_type = result_type_with_refs.peel_refs()
&& is_type_diagnostic_item(cx, result_type, sym::Result)
// do not lint if the closure is called using an iterator (see #1141)
if_chain! {
if let Some(parent) = get_parent_expr(self.cx, expr);
- if let ExprKind::MethodCall(_, [self_arg, ..], _) = &parent.kind;
+ if let ExprKind::MethodCall(_, self_arg, ..) = &parent.kind;
let caller = self.cx.typeck_results().expr_ty(self_arg);
if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator);
if implements_trait(self.cx, caller, iter_id, &[]);
);
}
} else {
- let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
+ let span =
+ block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
if span.from_expansion() || expr.span.from_expansion() {
return;
}
))
})
},
- ExprKind::MethodCall(path, args, _) if args.len() == 1 => {
- let type_of_receiver = cx.typeck_results().expr_ty(&args[0]);
+ ExprKind::MethodCall(path, receiver, [], _) => {
+ let type_of_receiver = cx.typeck_results().expr_ty(receiver);
if !is_type_diagnostic_item(cx, type_of_receiver, sym::Option)
&& !is_type_diagnostic_item(cx, type_of_receiver, sym::Result)
{
let path: &str = path.ident.name.as_str();
a == path
})
- .and_then(|(_, neg_method)| Some(format!("{}.{}()", snippet_opt(cx, args[0].span)?, neg_method)))
+ .and_then(|(_, neg_method)| Some(format!("{}.{}()", snippet_opt(cx, receiver.span)?, neg_method)))
},
_ => None,
}
if meets_msrv(msrv, msrvs::UNSIGNED_ABS)
&& let ty::Int(from) = cast_from.kind()
&& let ty::Uint(to) = cast_to.kind()
- && let ExprKind::MethodCall(method_path, args, _) = cast_expr.kind
+ && let ExprKind::MethodCall(method_path, receiver, ..) = cast_expr.kind
&& method_path.ident.name.as_str() == "abs"
{
let span = if from.bit_width() == to.bit_width() {
span,
&format!("casting the result of `{cast_from}::abs()` to {cast_to}"),
"replace with",
- format!("{}.unsigned_abs()", Sugg::hir(cx, &args[0], "..").maybe_par()),
+ format!("{}.unsigned_abs()", Sugg::hir(cx, receiver, "..").maybe_par()),
Applicability::MachineApplicable,
);
}
.saturating_sub(constant_int(cx, right).map_or(0, |s| u64::try_from(s).expect("shift too high"))),
_ => nbits,
},
- ExprKind::MethodCall(method, [left, right], _) => {
+ ExprKind::MethodCall(method, left, [right], _) => {
if signed {
return nbits;
}
};
apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::max_value()))
},
- ExprKind::MethodCall(method, [_, lo, hi], _) => {
+ ExprKind::MethodCall(method, _, [lo, hi], _) => {
if method.ident.as_str() == "clamp" {
//FIXME: make this a diagnostic item
if let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi)) {
}
nbits
},
- ExprKind::MethodCall(method, [_value], _) => {
+ ExprKind::MethodCall(method, _value, [], _) => {
if method.ident.name.as_str() == "signum" {
0 // do not lint if cast comes from a `signum` function
} else {
cx.typeck_results().expr_ty(expr),
);
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
- } else if let ExprKind::MethodCall(method_path, [self_arg, ..], _) = &expr.kind {
+ } else if let ExprKind::MethodCall(method_path, self_arg, ..) = &expr.kind {
if method_path.ident.name == sym!(cast)
&& let Some(generic_args) = method_path.args
&& let [GenericArg::Type(cast_to)] = generic_args.args
return false;
};
match parent.kind {
- ExprKind::MethodCall(name, [self_arg, ..], _) if self_arg.hir_id == e.hir_id => {
+ ExprKind::MethodCall(name, self_arg, ..) if self_arg.hir_id == e.hir_id => {
if matches!(name.ident.as_str(), "read_unaligned" | "write_unaligned")
&& let Some(def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id)
&& let Some(def_id) = cx.tcx.impl_of_method(def_id)
}
// Don't lint for the result of methods that always return non-negative values.
- if let ExprKind::MethodCall(path, _, _) = cast_op.kind {
+ if let ExprKind::MethodCall(path, ..) = cast_op.kind {
let mut method_name = path.ident.name.as_str();
let allowed_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"];
if_chain! {
if method_name == "unwrap";
if let Some(arglist) = method_chain_args(cast_op, &["unwrap"]);
- if let ExprKind::MethodCall(inner_path, _, _) = &arglist[0][0].kind;
+ if let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind;
then {
method_name = inner_path.ident.name.as_str();
}
impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
fn new(cx: &'a LateContext<'tcx>) -> Self {
- Self {
- ty_bounds: vec![TyBound::Nothing],
- cx,
- }
+ Self { ty_bounds: vec![TyBound::Nothing], cx }
}
/// Check whether a passed literal has potential to cause fallback or not.
}
return;
}
- },
+ }
- ExprKind::MethodCall(_, args, _) => {
+ ExprKind::MethodCall(_, receiver, args, _) => {
if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) {
let fn_sig = self.cx.tcx.fn_sig(def_id).skip_binder();
- for (expr, bound) in iter::zip(*args, fn_sig.inputs()) {
+ for (expr, bound) in
+ iter::zip(std::iter::once(*receiver).chain(args.iter()), fn_sig.inputs())
+ {
self.ty_bounds.push(TyBound::Ty(*bound));
self.visit_expr(expr);
self.ty_bounds.pop();
}
return;
}
- },
+ }
ExprKind::Struct(_, fields, base) => {
let ty = self.cx.typeck_results().expr_ty(expr);
return;
}
}
- },
+ }
ExprKind::Lit(lit) => {
let ty = self.cx.typeck_results().expr_ty(expr);
self.check_lit(lit, ty, expr.hir_id);
return;
- },
+ }
- _ => {},
+ _ => {}
}
walk_expr(self, expr);
} else {
self.ty_bounds.push(TyBound::Nothing);
}
- },
+ }
_ => self.ty_bounds.push(TyBound::Nothing),
}
expr: &'tcx Expr<'_>,
) -> Option<(RefOp, &'tcx Expr<'tcx>)> {
let (def_id, arg) = match expr.kind {
- ExprKind::MethodCall(_, [arg], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg),
+ ExprKind::MethodCall(_, arg, [], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg),
ExprKind::Call(
Expr {
kind: ExprKind::Path(path),
},
})
}),
- ExprKind::MethodCall(_, args, _) => {
+ ExprKind::MethodCall(_, receiver, args, _) => {
let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
- args.iter().position(|arg| arg.hir_id == child_id).map(|i| {
- if i == 0 {
- // Check for calls to trait methods where the trait is implemented on a reference.
- // Two cases need to be handled:
- // * `self` methods on `&T` will never have auto-borrow
- // * `&self` methods on `&T` can have auto-borrow, but `&self` methods on `T` will take
- // priority.
- if e.hir_id != child_id {
- Position::ReborrowStable(precedence)
- } else if let Some(trait_id) = cx.tcx.trait_of_item(id)
- && let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e))
- && let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
- && let subs = match cx
- .typeck_results()
- .node_substs_opt(parent.hir_id)
- .and_then(|subs| subs.get(1..))
- {
- Some(subs) => cx.tcx.mk_substs(subs.iter().copied()),
- None => cx.tcx.mk_substs(std::iter::empty::<ty::subst::GenericArg<'_>>()),
- } && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() {
- // Trait methods taking `&self`
- sub_ty
- } else {
- // Trait methods taking `self`
- arg_ty
- } && impl_ty.is_ref()
- && cx.tcx.infer_ctxt().enter(|infcx|
- infcx
- .type_implements_trait(trait_id, impl_ty, subs, cx.param_env)
- .must_apply_modulo_regions()
- )
+ if receiver.hir_id == child_id {
+ // Check for calls to trait methods where the trait is implemented on a reference.
+ // Two cases need to be handled:
+ // * `self` methods on `&T` will never have auto-borrow
+ // * `&self` methods on `&T` can have auto-borrow, but `&self` methods on `T` will take
+ // priority.
+ if e.hir_id != child_id {
+ return Some(Position::ReborrowStable(precedence))
+ } else if let Some(trait_id) = cx.tcx.trait_of_item(id)
+ && let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e))
+ && let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
+ && let subs = match cx
+ .typeck_results()
+ .node_substs_opt(parent.hir_id)
+ .and_then(|subs| subs.get(1..))
{
- Position::MethodReceiverRefImpl
+ Some(subs) => cx.tcx.mk_substs(subs.iter().copied()),
+ None => cx.tcx.mk_substs(std::iter::empty::<ty::subst::GenericArg<'_>>()),
+ } && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() {
+ // Trait methods taking `&self`
+ sub_ty
} else {
- Position::MethodReceiver
- }
+ // Trait methods taking `self`
+ arg_ty
+ } && impl_ty.is_ref()
+ && cx.tcx.infer_ctxt().enter(|infcx|
+ infcx
+ .type_implements_trait(trait_id, impl_ty, subs, cx.param_env)
+ .must_apply_modulo_regions()
+ )
+ {
+ return Some(Position::MethodReceiverRefImpl)
} else {
- let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i];
+ return Some(Position::MethodReceiver)
+ }
+ }
+ args.iter()
+ .position(|arg| arg.hir_id == child_id)
+ .map(|i| {
+ let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i + 1];
if let ty::Param(param_ty) = ty.kind() {
- needless_borrow_impl_arg_position(cx, parent, i, *param_ty, e, precedence, msrv)
+ needless_borrow_impl_arg_position(cx, parent, i + 1, *param_ty, e, precedence, msrv)
} else {
ty_auto_deref_stability(
cx,
- cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i)),
+ cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i + 1)),
precedence,
)
.position_for_arg()
}
- }
- })
+ })
},
ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess(name.name)),
ExprKind::Unary(UnOp::Deref, child) if child.hir_id == e.hir_id => Some(Position::Deref),
// check for `unwrap`
if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
- let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
+ let receiver_ty = self.typeck_results.expr_ty(&arglists[0].0).peel_refs();
if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option)
|| is_type_diagnostic_item(self.cx, receiver_ty, sym::Result)
{
match expr.kind {
ExprKind::MethodCall(
_,
+ map,
[
- map,
Expr {
kind: ExprKind::AddrOf(_, _, key),
span: key_span,
value: &'tcx Expr<'tcx>,
}
fn try_parse_insert<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<InsertExpr<'tcx>> {
- if let ExprKind::MethodCall(_, [map, key, value], _) = expr.kind {
+ if let ExprKind::MethodCall(_, map, [key, value], _) = expr.kind {
let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
if match_def_path(cx, id, &paths::BTREEMAP_INSERT) || match_def_path(cx, id, &paths::HASHMAP_INSERT) {
Some(InsertExpr { map, key, value })
if !is_adjusted(cx, &body.value);
if let ExprKind::Call(callee, args) = body.value.kind;
if let ExprKind::Path(_) = callee.kind;
- if check_inputs(cx, body.params, args);
+ if check_inputs(cx, body.params, None, args);
let callee_ty = cx.typeck_results().expr_ty_adjusted(callee);
let call_ty = cx.typeck_results().type_dependent_def_id(body.value.hir_id)
.map_or(callee_ty, |id| cx.tcx.type_of(id));
if_chain!(
if !is_adjusted(cx, &body.value);
- if let ExprKind::MethodCall(path, args, _) = body.value.kind;
- if check_inputs(cx, body.params, args);
+ if let ExprKind::MethodCall(path, receiver, args, _) = body.value.kind;
+ if check_inputs(cx, body.params, Some(receiver), args);
let method_def_id = cx.typeck_results().type_dependent_def_id(body.value.hir_id).unwrap();
let substs = cx.typeck_results().node_substs(body.value.hir_id);
let call_ty = cx.tcx.bound_type_of(method_def_id).subst(cx.tcx, substs);
}
}
-fn check_inputs(cx: &LateContext<'_>, params: &[Param<'_>], call_args: &[Expr<'_>]) -> bool {
- if params.len() != call_args.len() {
+fn check_inputs(
+ cx: &LateContext<'_>,
+ params: &[Param<'_>],
+ receiver: Option<&Expr<'_>>,
+ call_args: &[Expr<'_>],
+) -> bool {
+ if receiver.map_or(params.len() != call_args.len(), |_| params.len() != call_args.len() + 1) {
return false;
}
let binding_modes = cx.typeck_results().pat_binding_modes();
- std::iter::zip(params, call_args).all(|(param, arg)| {
+ let check_inputs = |param: &Param<'_>, arg| {
match param.pat.kind {
PatKind::Binding(_, id, ..) if path_to_local_id(arg, id) => {},
_ => return false,
},
_ => false,
}
- })
+ };
+ std::iter::zip(params, receiver.into_iter().chain(call_args.iter()))
+ .all(|(param, arg)| check_inputs(param, arg))
}
fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure_ty: Ty<'tcx>, call_ty: Ty<'tcx>) -> bool {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
// match call to unwrap
- if let ExprKind::MethodCall(unwrap_fun, [write_call], _) = expr.kind;
+ if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind;
if unwrap_fun.ident.name == sym::unwrap;
// match call to write_fmt
- if let ExprKind::MethodCall(write_fun, [write_recv, write_arg], _) = look_in_block(cx, &write_call.kind);
+ if let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = look_in_block(cx, &write_call.kind);
if write_fun.ident.name == sym!(write_fmt);
// match calls to std::io::stdout() / std::io::stderr ()
if let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() {
// check for `unwrap`
if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
- let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
+ let receiver_ty = self.typeck_results.expr_ty(&arglists[0].0).peel_refs();
if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option)
|| is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result)
{
suggestion.maybe_par()
}
-fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
- if let Some(method) = get_specialized_log_method(cx, &args[1]) {
+fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
+ if let Some(method) = get_specialized_log_method(cx, &args[0]) {
span_lint_and_sugg(
cx,
SUBOPTIMAL_FLOPS,
expr.span,
"logarithm for bases 2, 10 and e can be computed more accurately",
"consider using",
- format!("{}.{}()", Sugg::hir(cx, &args[0], "..").maybe_par(), method),
+ format!("{}.{}()", Sugg::hir(cx, receiver, "..").maybe_par(), method),
Applicability::MachineApplicable,
);
}
// TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and
// suggest usage of `(x + (y - 1)).ln_1p()` instead
-fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
+fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Add, ..
},
lhs,
rhs,
- ) = &args[0].kind
+ ) = receiver.kind
{
let recv = match (
constant(cx, cx.typeck_results(), lhs),
}
}
-fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
+fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
// Check receiver
- if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
+ if let Some((value, _)) = constant(cx, cx.typeck_results(), receiver) {
let method = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
"exp"
} else if F32(2.0) == value || F64(2.0) == value {
expr.span,
"exponent for bases 2 and e can be computed more accurately",
"consider using",
- format!("{}.{}()", prepare_receiver_sugg(cx, &args[1]), method),
+ format!("{}.{}()", prepare_receiver_sugg(cx, &args[0]), method),
Applicability::MachineApplicable,
);
}
// Check argument
- if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[1]) {
+ if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
(
SUBOPTIMAL_FLOPS,
"square-root of a number can be computed more efficiently and accurately",
- format!("{}.sqrt()", Sugg::hir(cx, &args[0], "..").maybe_par()),
+ format!("{}.sqrt()", Sugg::hir(cx, receiver, "..").maybe_par()),
)
} else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value {
(
IMPRECISE_FLOPS,
"cube-root of a number can be computed more accurately",
- format!("{}.cbrt()", Sugg::hir(cx, &args[0], "..").maybe_par()),
+ format!("{}.cbrt()", Sugg::hir(cx, receiver, "..").maybe_par()),
)
} else if let Some(exponent) = get_integer_from_float_constant(&value) {
(
"exponentiation with integer powers can be computed more efficiently",
format!(
"{}.powi({})",
- Sugg::hir(cx, &args[0], "..").maybe_par(),
+ Sugg::hir(cx, receiver, "..").maybe_par(),
numeric_literal::format(&exponent.to_string(), None, false)
),
)
}
}
-fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
- if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[1]) {
+fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
+ if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
if value == Int(2) {
if let Some(parent) = get_parent_expr(cx, expr) {
if let Some(grandparent) = get_parent_expr(cx, parent) {
- if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, args, _) = grandparent.kind {
- if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
+ if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = grandparent.kind
+ {
+ if method_name.as_str() == "sqrt" && detect_hypot(cx, receiver).is_some() {
return;
}
}
"consider using",
format!(
"{}.mul_add({}, {})",
- Sugg::hir(cx, &args[0], "..").maybe_par(),
- Sugg::hir(cx, &args[0], ".."),
+ Sugg::hir(cx, receiver, "..").maybe_par(),
+ Sugg::hir(cx, receiver, ".."),
Sugg::hir(cx, other_addend, ".."),
),
Applicability::MachineApplicable,
}
}
-fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> {
+fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option<String> {
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Add, ..
},
add_lhs,
add_rhs,
- ) = args[0].kind
+ ) = receiver.kind
{
// check if expression of the form x * x + y * y
if_chain! {
if_chain! {
if let ExprKind::MethodCall(
PathSegment { ident: lmethod_name, .. },
- [largs_0, largs_1, ..],
+ largs_0, [largs_1, ..],
_
) = &add_lhs.kind;
if let ExprKind::MethodCall(
PathSegment { ident: rmethod_name, .. },
- [rargs_0, rargs_1, ..],
+ rargs_0, [rargs_1, ..],
_
) = &add_rhs.kind;
if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi";
None
}
-fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
- if let Some(message) = detect_hypot(cx, args) {
+fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
+ if let Some(message) = detect_hypot(cx, receiver) {
span_lint_and_sugg(
cx,
IMPRECISE_FLOPS,
if cx.typeck_results().expr_ty(lhs).is_floating_point();
if let Some((value, _)) = constant(cx, cx.typeck_results(), rhs);
if F32(1.0) == value || F64(1.0) == value;
- if let ExprKind::MethodCall(path, [self_arg, ..], _) = &lhs.kind;
+ if let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind;
if cx.typeck_results().expr_ty(self_arg).is_floating_point();
if path.ident.name.as_str() == "exp";
then {
) = &expr.kind
{
if let Some(parent) = get_parent_expr(cx, expr) {
- if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, args, _) = parent.kind {
- if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
+ if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = parent.kind {
+ if method_name.as_str() == "sqrt" && detect_hypot(cx, receiver).is_some() {
return;
}
}
fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool {
if_chain! {
- if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, args_a, _) = expr_a.kind;
- if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, args_b, _) = expr_b.kind;
+ if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, args_a, _) = expr_a.kind;
+ if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, args_b, _) = expr_b.kind;
then {
return method_name_a.as_str() == method_name_b.as_str() &&
args_a.len() == args_b.len() &&
(
["ln", "log2", "log10"].contains(&method_name_a.as_str()) ||
- method_name_a.as_str() == "log" && args_a.len() == 2 && eq_expr_value(cx, &args_a[1], &args_b[1])
+ method_name_a.as_str() == "log" && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0])
);
}
}
rhs,
) = &expr.kind;
if are_same_base_logs(cx, lhs, rhs);
- if let ExprKind::MethodCall(_, [largs_self, ..], _) = &lhs.kind;
- if let ExprKind::MethodCall(_, [rargs_self, ..], _) = &rhs.kind;
+ if let ExprKind::MethodCall(_, largs_self, ..) = &lhs.kind;
+ if let ExprKind::MethodCall(_, rargs_self, ..) = &rhs.kind;
then {
span_lint_and_sugg(
cx,
return;
}
- if let ExprKind::MethodCall(path, args, _) = &expr.kind {
- let recv_ty = cx.typeck_results().expr_ty(&args[0]);
+ if let ExprKind::MethodCall(path, receiver, args, _) = &expr.kind {
+ let recv_ty = cx.typeck_results().expr_ty(receiver);
if recv_ty.is_floating_point() {
match path.ident.name.as_str() {
- "ln" => check_ln1p(cx, expr, args),
- "log" => check_log_base(cx, expr, args),
- "powf" => check_powf(cx, expr, args),
- "powi" => check_powi(cx, expr, args),
- "sqrt" => check_hypot(cx, expr, args),
+ "ln" => check_ln1p(cx, expr, receiver),
+ "log" => check_log_base(cx, expr, receiver, args),
+ "powf" => check_powf(cx, expr, receiver, args),
+ "powi" => check_powi(cx, expr, receiver, args),
+ "sqrt" => check_hypot(cx, expr, receiver),
_ => {},
}
}
}
}
-fn check_format_in_format_args(cx: &LateContext<'_>, call_site: Span, name: Symbol, arg: &Expr<'_>) {
+fn check_format_in_format_args(
+ cx: &LateContext<'_>,
+ call_site: Span,
+ name: Symbol,
+ arg: &Expr<'_>,
+) {
let expn_data = arg.span.ctxt().outer_expn_data();
if expn_data.call_site.from_expansion() {
return;
fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Expr<'_>) {
if_chain! {
if !value.span.from_expansion();
- if let ExprKind::MethodCall(_, [receiver], _) = value.kind;
+ if let ExprKind::MethodCall(_, receiver, [], _) = value.kind;
if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id);
if is_diag_trait_item(cx, method_def_id, sym::ToString);
let receiver_ty = cx.typeck_results().expr_ty(receiver);
// Returns true if `hir_id` is referred to by multiple format params
fn is_aliased(args: &FormatArgsExpn<'_>, hir_id: HirId) -> bool {
- args.params()
- .filter(|param| param.value.hir_id == hir_id)
- .at_most_one()
- .is_err()
+ args.params().filter(|param| param.value.hir_id == hir_id).at_most_one().is_err()
}
fn count_needed_derefs<'tcx, I>(mut ty: Ty<'tcx>, mut iter: I) -> (usize, Ty<'tcx>)
let mut n_total = 0;
let mut n_needed = 0;
loop {
- if let Some(Adjustment {
- kind: Adjust::Deref(overloaded_deref),
- target,
- }) = iter.next()
- {
+ if let Some(Adjustment { kind: Adjust::Deref(overloaded_deref), target }) = iter.next() {
n_total += 1;
if overloaded_deref.is_some() {
n_needed = n_total;
fn check_to_string_in_display(cx: &LateContext<'_>, expr: &Expr<'_>) {
if_chain! {
// Get the hir_id of the object we are calling the method on
- if let ExprKind::MethodCall(path, [ref self_arg, ..], _) = expr.kind;
+ if let ExprKind::MethodCall(path, self_arg, ..) = expr.kind;
// Is the method to_string() ?
if path.ident.name == sym::to_string;
// Is the method a part of the ToString trait? (i.e. not to_string() implemented
impl<'tcx> LateLintPass<'tcx> for FormatPushString {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
let arg = match expr.kind {
- ExprKind::MethodCall(_, [_, arg], _) => {
+ ExprKind::MethodCall(_, _, [arg], _) => {
if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) &&
match_def_path(cx, fn_def_id, &paths::PUSH_STR) {
arg
return;
}
match expr.kind {
- Call(_, args) | MethodCall(_, args, _) => {
+ Call(_, args) => {
let mut tys = DefIdSet::default();
for arg in args {
if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
tys.clear();
}
},
+ MethodCall(_, receiver, args, _) => {
+ let mut tys = DefIdSet::default();
+ for arg in std::iter::once(receiver).chain(args.iter()) {
+ if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
+ && is_mutable_ty(
+ self.cx,
+ self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg),
+ arg.span,
+ &mut tys,
+ )
+ && is_mutated_static(arg)
+ {
+ self.mutates_static = true;
+ return;
+ }
+ tys.clear();
+ }
+ },
Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target) => {
self.mutates_static |= is_mutated_static(target);
},
}
}
},
- hir::ExprKind::MethodCall(_, args, _) => {
+ hir::ExprKind::MethodCall(_, receiver, args, _) => {
let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap();
let base_type = self.cx.tcx.type_of(def_id);
if type_is_unsafe_function(self.cx, base_type) {
+ self.check_arg(receiver);
for arg in args {
self.check_arg(arg);
}
fn is_mutex_lock_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
if_chain! {
- if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
+ if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind;
if path.ident.as_str() == "lock";
let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
if is_type_diagnostic_item(cx, ty, sym::Mutex);
MaybeInfinite => (MAYBE_INFINITE_ITER, "possible infinite iteration detected"),
Finite => {
return;
- },
+ }
};
span_lint(cx, lint, expr.span, msg);
}
/// is an upper bound, e.g., some methods can return a possibly
/// infinite iterator at worst, e.g., `take_while`.
const HEURISTICS: [(&str, usize, Heuristic, Finiteness); 19] = [
- ("zip", 2, All, Infinite),
- ("chain", 2, Any, Infinite),
- ("cycle", 1, Always, Infinite),
- ("map", 2, First, Infinite),
- ("by_ref", 1, First, Infinite),
- ("cloned", 1, First, Infinite),
- ("rev", 1, First, Infinite),
- ("inspect", 1, First, Infinite),
- ("enumerate", 1, First, Infinite),
- ("peekable", 2, First, Infinite),
- ("fuse", 1, First, Infinite),
- ("skip", 2, First, Infinite),
- ("skip_while", 1, First, Infinite),
- ("filter", 2, First, Infinite),
- ("filter_map", 2, First, Infinite),
- ("flat_map", 2, First, Infinite),
- ("unzip", 1, First, Infinite),
- ("take_while", 2, First, MaybeInfinite),
- ("scan", 3, First, MaybeInfinite),
+ ("zip", 1, All, Infinite),
+ ("chain", 1, Any, Infinite),
+ ("cycle", 0, Always, Infinite),
+ ("map", 1, First, Infinite),
+ ("by_ref", 0, First, Infinite),
+ ("cloned", 0, First, Infinite),
+ ("rev", 0, First, Infinite),
+ ("inspect", 0, First, Infinite),
+ ("enumerate", 0, First, Infinite),
+ ("peekable", 1, First, Infinite),
+ ("fuse", 0, First, Infinite),
+ ("skip", 1, First, Infinite),
+ ("skip_while", 0, First, Infinite),
+ ("filter", 1, First, Infinite),
+ ("filter_map", 1, First, Infinite),
+ ("flat_map", 1, First, Infinite),
+ ("unzip", 0, First, Infinite),
+ ("take_while", 1, First, MaybeInfinite),
+ ("scan", 2, First, MaybeInfinite),
];
fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
match expr.kind {
- ExprKind::MethodCall(method, args, _) => {
+ ExprKind::MethodCall(method, receiver, args, _) => {
for &(name, len, heuristic, cap) in &HEURISTICS {
if method.ident.name.as_str() == name && args.len() == len {
return (match heuristic {
Always => Infinite,
- First => is_infinite(cx, &args[0]),
- Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])),
- All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])),
+ First => is_infinite(cx, receiver),
+ Any => is_infinite(cx, receiver).or(is_infinite(cx, &args[0])),
+ All => is_infinite(cx, receiver).and(is_infinite(cx, &args[0])),
})
.and(cap);
}
}
- if method.ident.name == sym!(flat_map) && args.len() == 2 {
- if let ExprKind::Closure(&Closure { body, .. }) = args[1].kind {
+ if method.ident.name == sym!(flat_map) && args.len() == 1 {
+ if let ExprKind::Closure(&Closure { body, .. }) = args[0].kind {
let body = cx.tcx.hir().body(body);
return is_infinite(cx, &body.value);
}
/// the names and argument lengths of methods that *may* exhaust their
/// iterators
const POSSIBLY_COMPLETING_METHODS: [(&str, usize); 6] = [
- ("find", 2),
- ("rfind", 2),
- ("position", 2),
- ("rposition", 2),
- ("any", 2),
- ("all", 2),
+ ("find", 1),
+ ("rfind", 1),
+ ("position", 1),
+ ("rposition", 1),
+ ("any", 1),
+ ("all", 1),
];
/// the names and argument lengths of methods that *always* exhaust
/// their iterators
const COMPLETING_METHODS: [(&str, usize); 12] = [
- ("count", 1),
- ("fold", 3),
- ("for_each", 2),
- ("partition", 2),
- ("max", 1),
- ("max_by", 2),
- ("max_by_key", 2),
- ("min", 1),
- ("min_by", 2),
- ("min_by_key", 2),
- ("sum", 1),
- ("product", 1),
+ ("count", 0),
+ ("fold", 2),
+ ("for_each", 1),
+ ("partition", 1),
+ ("max", 0),
+ ("max_by", 1),
+ ("max_by_key", 1),
+ ("min", 0),
+ ("min_by", 1),
+ ("min_by_key", 1),
+ ("sum", 0),
+ ("product", 0),
];
/// the paths of types that are known to be infinitely allocating
fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
match expr.kind {
- ExprKind::MethodCall(method, args, _) => {
+ ExprKind::MethodCall(method, receiver, args, _) => {
for &(name, len) in &COMPLETING_METHODS {
if method.ident.name.as_str() == name && args.len() == len {
- return is_infinite(cx, &args[0]);
+ return is_infinite(cx, receiver);
}
}
for &(name, len) in &POSSIBLY_COMPLETING_METHODS {
if method.ident.name.as_str() == name && args.len() == len {
- return MaybeInfinite.and(is_infinite(cx, &args[0]));
+ return MaybeInfinite.and(is_infinite(cx, receiver));
}
}
- if method.ident.name == sym!(last) && args.len() == 1 {
- let not_double_ended = cx
- .tcx
- .get_diagnostic_item(sym::DoubleEndedIterator)
- .map_or(false, |id| {
- !implements_trait(cx, cx.typeck_results().expr_ty(&args[0]), id, &[])
+ if method.ident.name == sym!(last) && args.is_empty() {
+ let not_double_ended =
+ cx.tcx.get_diagnostic_item(sym::DoubleEndedIterator).map_or(false, |id| {
+ !implements_trait(cx, cx.typeck_results().expr_ty(receiver), id, &[])
});
if not_double_ended {
- return is_infinite(cx, &args[0]);
+ return is_infinite(cx, receiver);
}
} else if method.ident.name == sym!(collect) {
let ty = cx.typeck_results().expr_ty(expr);
.iter()
.any(|diag_item| is_type_diagnostic_item(cx, ty, *diag_item))
{
- return is_infinite(cx, &args[0]);
+ return is_infinite(cx, receiver);
}
}
},
}
fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) {
- if let (&ExprKind::MethodCall(method_path, args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) {
+ if let (&ExprKind::MethodCall(method_path, receiver, args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) {
// check if we are in an is_empty() method
if let Some(name) = get_item_name(cx, method) {
if name.as_str() == "is_empty" {
}
}
- check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to);
+ check_len(cx, span, method_path.ident.name, receiver, args, &lit.node, op, compare_to);
} else {
check_empty_expr(cx, span, method, lit, op);
}
cx: &LateContext<'_>,
span: Span,
method_name: Symbol,
+ receiver: &Expr<'_>,
args: &[Expr<'_>],
lit: &LitKind,
op: &str,
return;
}
- if method_name == sym::len && args.len() == 1 && has_is_empty(cx, &args[0]) {
+ if method_name == sym::len && args.is_empty() && has_is_empty(cx, receiver) {
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
cx,
format!(
"{}{}.is_empty()",
op,
- snippet_with_applicability(cx, args[0].span, "_", &mut applicability)
+ snippet_with_applicability(cx, receiver.span, "_", &mut applicability)
),
applicability,
);
let print_limit = |end: &Expr<'_>, end_str: &str, base: &Expr<'_>, sugg: MinifyingSugg<'static>| {
if_chain! {
- if let ExprKind::MethodCall(method, [recv], _) = end.kind;
+ if let ExprKind::MethodCall(method, recv, [], _) = end.kind;
if method.ident.name == sym::len;
if path_to_local(recv) == path_to_local(base);
then {
fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
if_chain! {
- if let ExprKind::MethodCall(method, [arg], _) = expr.kind;
+ if let ExprKind::MethodCall(method, arg, [], _) = expr.kind;
if method.ident.name == sym::clone;
then { arg } else { expr }
}
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>) {
if_chain! {
if let ExprKind::Block(Block { stmts: [], expr: None, ..}, _) = body.kind;
- if let ExprKind::MethodCall(method, [callee, ..], _) = unpack_cond(cond).kind;
+ if let ExprKind::MethodCall(method, callee, ..) = unpack_cond(cond).kind;
if [sym::load, sym::compare_exchange, sym::compare_exchange_weak].contains(&method.ident.name);
if let ty::Adt(def, _substs) = cx.typeck_results().expr_ty(callee).kind();
if cx.tcx.is_diagnostic_item(sym::AtomicBool, def.did());
fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) {
let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
- if let ExprKind::MethodCall(method, [self_arg], _) = arg.kind {
+ if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind {
let method_name = method.ident.as_str();
// check for looping over x.iter() or x.iter_mut(), could use &x or &mut x
match method_name {
}
fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) {
if_chain! {
- if let ExprKind::MethodCall(method, args, _) = expr.kind;
- if let ExprKind::MethodCall(chain_method, _, _) = args[0].kind;
- if chain_method.ident.name == sym!(collect) && is_trait_method(cx, &args[0], sym::Iterator);
+ if let ExprKind::MethodCall(method, receiver, args, _) = expr.kind;
+ if let ExprKind::MethodCall(chain_method, ..) = receiver.kind;
+ if chain_method.ident.name == sym!(collect) && is_trait_method(cx, receiver, sym::Iterator);
then {
- let ty = cx.typeck_results().expr_ty(&args[0]);
+ let ty = cx.typeck_results().expr_ty(receiver);
let mut applicability = Applicability::MaybeIncorrect;
let is_empty_sugg = "next().is_none()".to_string();
let method_name = method.ident.name.as_str();
"len" => "count()".to_string(),
"is_empty" => is_empty_sugg,
"contains" => {
- let contains_arg = snippet_with_applicability(cx, args[1].span, "??", &mut applicability);
+ let contains_arg = snippet_with_applicability(cx, args[0].span, "??", &mut applicability);
let (arg, pred) = contains_arg
.strip_prefix('&')
.map_or(("&x", &*contains_arg), |s| ("x", s));
if let StmtKind::Local(local) = stmt.kind;
if let PatKind::Binding(_, id, ..) = local.pat.kind;
if let Some(init_expr) = local.init;
- if let ExprKind::MethodCall(method_name, &[ref iter_source], ..) = init_expr.kind;
+ if let ExprKind::MethodCall(method_name, iter_source, [], ..) = init_expr.kind;
if method_name.ident.name == sym!(collect) && is_trait_method(cx, init_expr, sym::Iterator);
let ty = cx.typeck_results().expr_ty(init_expr);
if is_type_diagnostic_item(cx, ty, sym::Vec) ||
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
// Check function calls on our collection
- if let ExprKind::MethodCall(method_name, [recv, args @ ..], _) = &expr.kind {
+ if let ExprKind::MethodCall(method_name, recv, [args @ ..], _) = &expr.kind {
if method_name.ident.name == sym!(collect) && is_trait_method(self.cx, expr, sym::Iterator) {
self.current_mutably_captured_ids = get_captured_ids(self.cx, self.cx.typeck_results().expr_ty(recv));
self.visit_expr(recv);
fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool {
if_chain! {
- if let ExprKind::MethodCall(method, [recv], _) = expr.kind;
+ if let ExprKind::MethodCall(method, recv, [], _) = expr.kind;
if method.ident.name == sym::len;
if let ExprKind::Path(QPath::Resolved(_, path)) = recv.kind;
if path.segments.len() == 1;
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if_chain! {
// a range index op
- if let ExprKind::MethodCall(meth, [args_0, args_1, ..], _) = &expr.kind;
+ if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind;
if (meth.ident.name == sym::index && match_trait_method(self.cx, expr, &paths::INDEX))
|| (meth.ident.name == sym::index_mut && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
if !self.check(args_1, args_0, expr);
self.visit_expr(expr);
}
},
- ExprKind::MethodCall(_, args, _) => {
+ ExprKind::MethodCall(_, receiver, args, _) => {
let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
- for (ty, expr) in iter::zip(self.cx.tcx.fn_sig(def_id).inputs().skip_binder(), args) {
+ for (ty, expr) in iter::zip(
+ self.cx.tcx.fn_sig(def_id).inputs().skip_binder(),
+ std::iter::once(receiver).chain(args.iter()),
+ ) {
self.prefer_mutable = false;
if let ty::Ref(_, _, mutbl) = *ty.kind() {
if mutbl == Mutability::Mut {
| ExprKind::Repeat(e, _)
| ExprKind::DropTemps(e) => never_loop_expr(e, main_loop_id),
ExprKind::Let(let_expr) => never_loop_expr(let_expr.init, main_loop_id),
- ExprKind::Array(es) | ExprKind::MethodCall(_, es, _) | ExprKind::Tup(es) => {
- never_loop_expr_all(&mut es.iter(), main_loop_id)
+ ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(&mut es.iter(), main_loop_id),
+ ExprKind::MethodCall(_, receiver, es, _) => {
+ never_loop_expr_all(&mut std::iter::once(receiver).chain(es.iter()), main_loop_id)
},
ExprKind::Struct(_, fields, base) => {
let fields = never_loop_expr_all(&mut fields.iter().map(|f| f.expr), main_loop_id);
InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
never_loop_expr(expr, main_loop_id)
},
- InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter(), main_loop_id),
+ InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter().copied(), main_loop_id),
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
- never_loop_expr_all(&mut once(in_expr).chain(out_expr.iter()), main_loop_id)
+ never_loop_expr_all(&mut once(*in_expr).chain(out_expr.iter().copied()), main_loop_id)
},
InlineAsmOperand::Const { .. }
| InlineAsmOperand::SymFn { .. }
if_chain! {
// Extract method being called
if let StmtKind::Semi(semi_stmt) = &stmt.kind;
- if let ExprKind::MethodCall(path, args, _) = &semi_stmt.kind;
+ if let ExprKind::MethodCall(path, self_expr, args, _) = &semi_stmt.kind;
// Figure out the parameters for the method call
- if let Some(self_expr) = args.get(0);
- if let Some(pushed_item) = args.get(1);
+ if let Some(pushed_item) = args.get(0);
// Check that the method being called is push() on a Vec
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec);
if path.ident.name.as_str() == "push";
) => (arg, "&mut "),
ExprKind::MethodCall(
method,
- [
- Expr {
- kind: ExprKind::Array([arg]),
- ..
- },
- ],
+ Expr {
+ kind: ExprKind::Array([arg]),
+ ..
+ },
+ [],
_,
) if method.ident.name == rustc_span::sym::iter => (arg, "&"),
ExprKind::MethodCall(
method,
- [
- Expr {
- kind: ExprKind::Array([arg]),
- ..
- },
- ],
+ Expr {
+ kind: ExprKind::Array([arg]),
+ ..
+ },
+ [],
_,
) if method.ident.name.as_str() == "iter_mut" => (arg, "&mut "),
ExprKind::MethodCall(
method,
- [
- Expr {
- kind: ExprKind::Array([arg]),
- ..
- },
- ],
+ Expr {
+ kind: ExprKind::Array([arg]),
+ ..
+ },
+ [],
_,
) if method.ident.name == rustc_span::sym::into_iter => (arg, ""),
// Only check for arrays edition 2021 or later, as this case will trigger a compiler error otherwise.
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) {
let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) {
([stmt, stmts @ ..], expr) => {
- if let StmtKind::Local(&Local { init: Some(e), els: None, .. }) | StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind {
+ if let StmtKind::Local(&Local {
+ init: Some(e),
+ els: None,
+ ..
+ })
+ | StmtKind::Semi(e)
+ | StmtKind::Expr(e) = stmt.kind
+ {
(e, !stmts.is_empty() || expr.is_some())
} else {
return;
if let Res::Def(_, pat_did) = pat_path.res;
if match_def_path(cx, pat_did, &paths::OPTION_SOME);
// check for call to `Iterator::next`
- if let ExprKind::MethodCall(method_name, [iter_expr], _) = let_expr.kind;
+ if let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind;
if method_name.ident.name == sym::next;
if is_trait_method(cx, let_expr, sym::Iterator);
if let Some(iter_expr_struct) = try_parse_iter_expr(cx, iter_expr);
if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id();
if cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id);
then {
- cx.typeck_results().node_substs(count_func.hir_id).types().next().map(|resolved_ty| (real_ty, resolved_ty))
+ cx.typeck_results().node_substs(count_func.hir_id).types().next().map(|resolved_ty| (*real_ty, resolved_ty))
} else {
None
}
fn is_ty_conversion(expr: &Expr<'_>) -> bool {
if let ExprKind::Cast(..) = expr.kind {
true
- } else if let ExprKind::MethodCall(path, [_], _) = expr.kind
+ } else if let ExprKind::MethodCall(path, _, [], _) = expr.kind
&& path.ident.name == rustc_span::sym::try_into
{
// This is only called for `usize` which implements `TryInto`. Therefore,
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
if let Some(parent_expr) = get_parent_expr(cx, expr)
&& let Assign(left_expr, collect_expr, _) = &parent_expr.kind
- && let hir::ExprKind::MethodCall(seg, _, _) = &collect_expr.kind
+ && let hir::ExprKind::MethodCall(seg, ..) = &collect_expr.kind
&& seg.args.is_none()
- && let hir::ExprKind::MethodCall(_, [target_expr], _) = &collect_expr.kind
+ && let hir::ExprKind::MethodCall(_, target_expr, [], _) = &collect_expr.kind
&& let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id)
&& match_def_path(cx, collect_def_id, &paths::CORE_ITER_COLLECT) {
check_into_iter(cx, parent_expr, left_expr, target_expr, self.msrv);
target_expr: &hir::Expr<'_>,
msrv: Option<RustcVersion>,
) {
- if let hir::ExprKind::MethodCall(_, [into_iter_expr, _], _) = &target_expr.kind
+ if let hir::ExprKind::MethodCall(_, into_iter_expr, [_], _) = &target_expr.kind
&& let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
&& match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
- && let hir::ExprKind::MethodCall(_, [struct_expr], _) = &into_iter_expr.kind
+ && let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &into_iter_expr.kind
&& let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id)
&& match_def_path(cx, into_iter_def_id, &paths::CORE_ITER_INTO_ITER)
&& match_acceptable_type(cx, left_expr, msrv)
target_expr: &hir::Expr<'_>,
msrv: Option<RustcVersion>,
) {
- if let hir::ExprKind::MethodCall(_, [filter_expr], _) = &target_expr.kind
+ if let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind
&& let Some(copied_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
&& (match_def_path(cx, copied_def_id, &paths::CORE_ITER_COPIED)
|| match_def_path(cx, copied_def_id, &paths::CORE_ITER_CLONED))
- && let hir::ExprKind::MethodCall(_, [iter_expr, _], _) = &filter_expr.kind
+ && let hir::ExprKind::MethodCall(_, iter_expr, [_], _) = &filter_expr.kind
&& let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id)
&& match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
- && let hir::ExprKind::MethodCall(_, [struct_expr], _) = &iter_expr.kind
+ && let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &iter_expr.kind
&& let Some(iter_expr_def_id) = cx.typeck_results().type_dependent_def_id(iter_expr.hir_id)
&& match_acceptable_def_path(cx, iter_expr_def_id)
&& match_acceptable_type(cx, left_expr, msrv)
msrv: Option<RustcVersion>,
) {
if meets_msrv(msrv, msrvs::STRING_RETAIN)
- && let hir::ExprKind::MethodCall(_, [filter_expr], _) = &target_expr.kind
+ && let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind
&& let Some(to_owned_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
&& match_def_path(cx, to_owned_def_id, &paths::TO_OWNED_METHOD)
- && let hir::ExprKind::MethodCall(_, [chars_expr, _], _) = &filter_expr.kind
+ && let hir::ExprKind::MethodCall(_, chars_expr, [_], _) = &filter_expr.kind
&& let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id)
&& match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
- && let hir::ExprKind::MethodCall(_, [str_expr], _) = &chars_expr.kind
+ && let hir::ExprKind::MethodCall(_, str_expr, [], _) = &chars_expr.kind
&& let Some(chars_expr_def_id) = cx.typeck_results().type_dependent_def_id(chars_expr.hir_id)
&& match_def_path(cx, chars_expr_def_id, &paths::STR_CHARS)
&& let ty = cx.typeck_results().expr_ty(str_expr).peel_refs()
}
fn suggest(cx: &LateContext<'_>, parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, filter_expr: &hir::Expr<'_>) {
- if let hir::ExprKind::MethodCall(_, [_, closure], _) = filter_expr.kind
+ if let hir::ExprKind::MethodCall(_, _, [closure], _) = filter_expr.kind
&& let hir::ExprKind::Closure(&hir::Closure { body, ..}) = closure.kind
&& let filter_body = cx.tcx.hir().body(body)
&& let [filter_params] = filter_body.params
ExprKind::Call(func, args) => {
parse_call(cx, expr.span, func, args);
},
- ExprKind::MethodCall(path_segment, args, _) => {
- parse_method_call(cx, expr.span, path_segment, args);
+ ExprKind::MethodCall(path_segment, receiver, ..) => {
+ parse_method_call(cx, expr.span, path_segment, receiver);
},
_ => (),
}
}
/// Tries to parse an expression as a method call, emitting the warning if necessary.
-fn parse_method_call(cx: &LateContext<'_>, span: Span, path_segment: &PathSegment<'_>, args: &[Expr<'_>]) {
- if args.is_empty() {
- // When parsing TryFrom::try_from(...).expect(...), we will have more than 1 arg.
- return;
- }
-
+fn parse_method_call(cx: &LateContext<'_>, span: Span, path_segment: &PathSegment<'_>, receiver: &Expr<'_>) {
let ident = path_segment.ident.as_str();
- let method_arg_kind = &args[0].kind;
+ let method_arg_kind = &receiver.kind;
if ["to_string", "to_owned", "into"].contains(&ident) && is_expr_kind_empty_str(method_arg_kind) {
warn_then_suggest(cx, span);
} else if let ExprKind::Call(func, args) = method_arg_kind {
if_chain! {
if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr);
- if let ExprKind::MethodCall(_, [target_arg, pattern], _) = cond.kind;
+ if let ExprKind::MethodCall(_, target_arg, [pattern], _) = cond.kind;
if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id);
if let ExprKind::Path(target_path) = &target_arg.kind;
then {
// Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise.
fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
if_chain! {
- if let ExprKind::MethodCall(_, [arg], _) = expr.kind;
+ if let ExprKind::MethodCall(_, arg, [], _) = expr.kind;
if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if match_def_path(cx, method_def_id, &paths::STR_LEN);
then {
)
}
-fn lint_map_unit_fn(cx: &LateContext<'_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr<'_>, map_args: &[hir::Expr<'_>]) {
- let var_arg = &map_args[0];
+fn lint_map_unit_fn(
+ cx: &LateContext<'_>,
+ stmt: &hir::Stmt<'_>,
+ expr: &hir::Expr<'_>,
+ map_args: (&hir::Expr<'_>, &[hir::Expr<'_>]),
+) {
+ let var_arg = &map_args.0;
let (map_type, variant, lint) = if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::Option) {
("Option", "Some", OPTION_MAP_UNIT_FN)
} else {
return;
};
- let fn_arg = &map_args[1];
+ let fn_arg = &map_args.1[0];
if is_unit_function(cx, fn_arg) {
let mut applicability = Applicability::MachineApplicable;
};
if_chain! {
- if let ExprKind::MethodCall(ok_path, [ref result_types_0, ..], _) = let_expr.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
+ if let ExprKind::MethodCall(ok_path, result_types_0, ..) = let_expr.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
if let PatKind::TupleStruct(QPath::Resolved(_, x), y, _) = let_pat.kind; //get operation
if method_chain_args(let_expr, &["ok"]).is_some(); //test to see if using ok() method use std::marker::Sized;
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(result_types_0), sym::Result);
impl<'a, 'tcx> Visitor<'tcx> for MatchExprVisitor<'a, 'tcx> {
fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
match ex.kind {
- ExprKind::MethodCall(segment, [receiver], _) if self.case_altered(segment.ident.as_str(), receiver) => {},
+ ExprKind::MethodCall(segment, receiver, [], _) if self.case_altered(segment.ident.as_str(), receiver) => {},
_ => walk_expr(self, ex),
}
}
// check that `while_let_on_iterator` lint does not trigger
if_chain! {
if keyword == "while";
- if let ExprKind::MethodCall(method_path, _, _) = let_expr.kind;
+ if let ExprKind::MethodCall(method_path, ..) = let_expr.kind;
if method_path.ident.name == sym::next;
if is_trait_method(cx, let_expr, sym::Iterator);
then {
self.is_chain_end = false;
match ex.kind {
- ExprKind::MethodCall(_, [ref expr, ..], _) => {
+ ExprKind::MethodCall(_, expr, ..) => {
self.visit_expr(expr);
}
ExprKind::Binary(_, left, right) => {
ExprKind::Index(..) |
ExprKind::Ret(..) |
ExprKind::Repeat(..) |
- ExprKind::Yield(..) |
- ExprKind::MethodCall(..) => walk_expr(self, ex),
+ ExprKind::Yield(..) => walk_expr(self, ex),
ExprKind::AddrOf(_, _, _) |
ExprKind::Block(_, _) |
ExprKind::Break(_, _) |
if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind();
if !is_local_used(cx, needle, arg_id);
then {
- let haystack = if let ExprKind::MethodCall(path, args, _) =
+ let haystack = if let ExprKind::MethodCall(path, receiver, [], _) =
filter_recv.kind {
let p = path.ident.name;
- if (p == sym::iter || p == sym!(iter_mut)) && args.len() == 1 {
- &args[0]
+ if p == sym::iter || p == sym!(iter_mut) {
+ receiver
} else {
filter_recv
}
if Some(id) == cx.tcx.lang_items().option_some_variant();
then {
let mut applicability = Applicability::MachineApplicable;
- let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0][0]).peel_refs();
+ let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0].0).peel_refs();
if *self_ty.kind() != ty::Str {
return false;
"like this",
format!("{}{}.{}({})",
if info.eq { "" } else { "!" },
- snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
+ snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
suggest,
snippet_with_applicability(cx, arg_char.span, "..", &mut applicability)),
applicability,
"like this",
format!("{}{}.{}('{}')",
if info.eq { "" } else { "!" },
- snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
+ snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
suggest,
c.escape_default()),
applicability,
/// Checks for the `CLONE_ON_COPY` lint.
#[allow(clippy::too_many_lines)]
-pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, args: &[Expr<'_>]) {
- let arg = match args {
- [arg] if method_name == sym::clone => arg,
- _ => return,
- };
+pub(super) fn check(
+ cx: &LateContext<'_>,
+ expr: &Expr<'_>,
+ method_name: Symbol,
+ receiver: &Expr<'_>,
+ args: &[Expr<'_>],
+) {
+ let arg = if method_name == sym::clone && args.is_empty() { receiver } else { return };
if cx
.typeck_results()
.type_dependent_def_id(expr.hir_id)
// &*x is a nop, &x.clone() is not
ExprKind::AddrOf(..) => return,
// (*x).func() is useless, x.clone().func() can work in case func borrows self
- ExprKind::MethodCall(_, [self_arg, ..], _)
+ ExprKind::MethodCall(_, self_arg, ..)
if expr.hir_id == self_arg.hir_id && ty != cx.typeck_results().expr_ty_adjusted(expr) =>
{
return;
hir_callee.kind,
ExprKind::Path(QPath::LangItem(rustc_hir::LangItem::TryTraitBranch, _, _))
),
- ExprKind::MethodCall(_, [self_arg, ..], _) if expr.hir_id == self_arg.hir_id => true,
+ ExprKind::MethodCall(_, self_arg, ..) if expr.hir_id == self_arg.hir_id => true,
ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
| ExprKind::Field(..)
| ExprKind::Index(..) => true,
use super::CLONE_ON_REF_PTR;
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
- if !(args.len() == 1 && method_name == sym::clone) {
+pub(super) fn check(
+ cx: &LateContext<'_>,
+ expr: &hir::Expr<'_>,
+ method_name: Symbol,
+ receiver: &hir::Expr<'_>,
+ args: &[hir::Expr<'_>],
+) {
+ if !(args.is_empty() && method_name == sym::clone) {
return;
}
- let arg = &args[0];
- let obj_ty = cx.typeck_results().expr_ty(arg).peel_refs();
+ let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs();
if let ty::Adt(_, subst) = obj_ty.kind() {
let caller_type = if is_type_diagnostic_item(cx, obj_ty, sym::Rc) {
return;
};
- let snippet = snippet_with_macro_callsite(cx, arg.span, "..");
+ let snippet = snippet_with_macro_callsite(cx, receiver.span, "..");
span_lint_and_sugg(
cx,
// If the parent node's `to` argument is the same as the `to` argument
// of the last replace call in the current chain, don't lint as it was already linted
if let Some(parent) = get_parent_expr(cx, expr)
- && let Some(("replace", [_, current_from, current_to], _)) = method_call(parent)
+ && let Some(("replace", _, [current_from, current_to], _)) = method_call(parent)
&& eq_expr_value(cx, to, current_to)
&& from_kind == cx.typeck_results().expr_ty(current_from).peel_refs().kind()
{
let mut from_args = VecDeque::new();
let _: Option<()> = for_each_expr(expr, |e| {
- if let Some(("replace", [_, from, to], _)) = method_call(e) {
+ if let Some(("replace", _, [from, to], _)) = method_call(e) {
if eq_expr_value(cx, to_arg, to) && cx.typeck_results().expr_ty(from).peel_refs().is_char() {
methods.push_front(e);
from_args.push_front(from);
.collect();
let app = Applicability::MachineApplicable;
let earliest_replace_call = replace_methods.methods.front().unwrap();
- if let Some((_, [..], span_lo)) = method_call(earliest_replace_call) {
+ if let Some((_, _, [..], span_lo)) = method_call(earliest_replace_call) {
span_lint_and_sugg(
cx,
COLLAPSIBLE_STR_REPLACE,
expr: &hir::Expr<'_>,
method_span: Span,
name: &str,
+ receiver: &'tcx hir::Expr<'tcx>,
args: &'tcx [hir::Expr<'tcx>],
) {
// Strip `&`, `as_ref()` and `as_str()` off `arg` until we're left with either a `String` or
loop {
arg_root = match &arg_root.kind {
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr) => expr,
- hir::ExprKind::MethodCall(method_name, call_args, _) => {
- if call_args.len() == 1
- && (method_name.ident.name == sym::as_str || method_name.ident.name == sym::as_ref)
- && {
- let arg_type = cx.typeck_results().expr_ty(&call_args[0]);
- let base_type = arg_type.peel_refs();
- *base_type.kind() == ty::Str || is_type_diagnostic_item(cx, base_type, sym::String)
- }
- {
- &call_args[0]
+ hir::ExprKind::MethodCall(method_name, receiver, [], ..) => {
+ if (method_name.ident.name == sym::as_str || method_name.ident.name == sym::as_ref) && {
+ let arg_type = cx.typeck_results().expr_ty(receiver);
+ let base_type = arg_type.peel_refs();
+ *base_type.kind() == ty::Str || is_type_diagnostic_item(cx, base_type, sym::String)
+ } {
+ receiver
} else {
break;
}
}
}
- if args.len() != 2 || name != "expect" || !is_call(&args[1].kind) {
+ if args.len() != 1 || name != "expect" || !is_call(&args[0].kind) {
return;
}
- let receiver_type = cx.typeck_results().expr_ty_adjusted(&args[0]);
+ let receiver_type = cx.typeck_results().expr_ty_adjusted(receiver);
let closure_args = if is_type_diagnostic_item(cx, receiver_type, sym::Option) {
"||"
} else if is_type_diagnostic_item(cx, receiver_type, sym::Result) {
return;
};
- let arg_root = get_arg_root(cx, &args[1]);
+ let arg_root = get_arg_root(cx, &args[0]);
let span_replace_word = method_span.with_hi(expr.span.hi());
if_chain! {
if is_type_diagnostic_item(cx, ty, sym::Vec);
//check source object
- if let ExprKind::MethodCall(src_method, [drain_vec, drain_arg], _) = &arg.kind;
+ if let ExprKind::MethodCall(src_method, drain_vec, [drain_arg], _) = &arg.kind;
if src_method.ident.as_str() == "drain";
let src_ty = cx.typeck_results().expr_ty(drain_vec);
//check if actual src type is mutable for code suggestion
let closure_expr = peel_blocks(&body.value);
let arg_id = body.params[0].pat.hir_id;
match closure_expr.kind {
- hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, args, _) => {
+ hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => {
if_chain! {
if ident.name == method_name;
- if let hir::ExprKind::Path(path) = &args[0].kind;
- if let Res::Local(ref local) = cx.qpath_res(path, args[0].hir_id);
+ if let hir::ExprKind::Path(path) = &receiver.kind;
+ if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id);
then {
return arg_id == *local
}
};
// closure ends with is_some() or is_ok()
if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
- if let ExprKind::MethodCall(path, [filter_arg], _) = filter_body.value.kind;
+ if let ExprKind::MethodCall(path, filter_arg, [], _) = filter_body.value.kind;
if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).peel_refs().ty_adt_def();
if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did()) {
Some(false)
if let [map_param] = map_body.params;
if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
// closure ends with expect() or unwrap()
- if let ExprKind::MethodCall(seg, [map_arg, ..], _) = map_body.value.kind;
+ if let ExprKind::MethodCall(seg, map_arg, ..) = map_body.value.kind;
if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or);
// .filter(..).map(|y| f(y).copied().unwrap())
// ~~~~
let map_arg_peeled = match map_arg.kind {
- ExprKind::MethodCall(method, [original_arg], _) if acceptable_methods(method) => {
+ ExprKind::MethodCall(method, original_arg, [], _) if acceptable_methods(method) => {
original_arg
},
_ => map_arg,
) = arg.kind
// LHS of subtraction is "x.len()"
- && let ExprKind::MethodCall(lhs_path, [lhs_recv], _) = &lhs.kind
+ && let ExprKind::MethodCall(lhs_path, lhs_recv, [], _) = &lhs.kind
&& lhs_path.ident.name == sym::len
// RHS of subtraction is 1
use super::INEFFICIENT_TO_STRING;
/// Checks for the `INEFFICIENT_TO_STRING` lint
-pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
+pub fn check<'tcx>(
+ cx: &LateContext<'tcx>,
+ expr: &hir::Expr<'_>,
+ method_name: Symbol,
+ receiver: &hir::Expr<'_>,
+ args: &[hir::Expr<'_>],
+) {
if_chain! {
- if args.len() == 1 && method_name == sym::to_string;
+ if args.is_empty() && method_name == sym::to_string;
if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if match_def_path(cx, to_string_meth_did, &paths::TO_STRING_METHOD);
if let Some(substs) = cx.typeck_results().node_substs_opt(expr.hir_id);
- let arg_ty = cx.typeck_results().expr_ty_adjusted(&args[0]);
+ let arg_ty = cx.typeck_results().expr_ty_adjusted(receiver);
let self_ty = substs.type_at(0);
let (deref_self_ty, deref_count) = walk_ptrs_ty_depth(self_ty);
if deref_count >= 1;
self_ty, deref_self_ty
));
let mut applicability = Applicability::MachineApplicable;
- let arg_snippet = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);
+ let arg_snippet = snippet_with_applicability(cx, receiver.span, "..", &mut applicability);
diag.span_suggestion(
expr.span,
"try dereferencing the receiver",
expr: &hir::Expr<'_>,
method_span: Span,
method_name: Symbol,
- args: &[hir::Expr<'_>],
+ receiver: &hir::Expr<'_>,
) {
- let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0]);
+ let self_ty = cx.typeck_results().expr_ty_adjusted(receiver);
if_chain! {
if let ty::Ref(..) = self_ty.kind();
if method_name == sym::into_iter;
&& range.end.map_or(true, |e| {
if range.limits == RangeLimits::HalfOpen
&& let ExprKind::Path(QPath::Resolved(None, container_path)) = container.kind
- && let ExprKind::MethodCall(name, [self_arg], _) = e.kind
+ && let ExprKind::MethodCall(name, self_arg, [], _) = e.kind
&& name.ident.name == sym::len
&& let ExprKind::Path(QPath::Resolved(None, path)) = self_arg.kind
{
}
}
},
- hir::ExprKind::MethodCall(method, [obj], _) => if_chain! {
+ hir::ExprKind::MethodCall(method, obj, [], _) => if_chain! {
if ident_eq(name, obj) && method.ident.name == sym::clone;
if let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id);
if let Some(trait_id) = cx.tcx.trait_of_item(fn_id);
]);
/// Extracts a method call name, args, and `Span` of the method name.
-fn method_call<'tcx>(recv: &'tcx hir::Expr<'tcx>) -> Option<(&'tcx str, &'tcx [hir::Expr<'tcx>], Span)> {
- if let ExprKind::MethodCall(path, args, _) = recv.kind {
- if !args.iter().any(|e| e.span.from_expansion()) {
+fn method_call<'tcx>(
+ recv: &'tcx hir::Expr<'tcx>,
+) -> Option<(&'tcx str, &'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>], Span)> {
+ if let ExprKind::MethodCall(path, receiver, args, _) = recv.kind {
+ if !args.iter().any(|e| e.span.from_expansion()) && !receiver.span.from_expansion() {
let name = path.ident.name.as_str();
- return Some((name, args, path.ident.span));
+ return Some((name, receiver, args, path.ident.span));
}
}
None
hir::ExprKind::Call(func, args) => {
from_iter_instead_of_collect::check(cx, expr, args, func);
},
- hir::ExprKind::MethodCall(method_call, args, _) => {
+ hir::ExprKind::MethodCall(method_call, receiver, args, _) => {
let method_span = method_call.ident.span;
- or_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), args);
- expect_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), args);
- clone_on_copy::check(cx, expr, method_call.ident.name, args);
- clone_on_ref_ptr::check(cx, expr, method_call.ident.name, args);
- inefficient_to_string::check(cx, expr, method_call.ident.name, args);
- single_char_add_str::check(cx, expr, args);
- into_iter_on_ref::check(cx, expr, method_span, method_call.ident.name, args);
- single_char_pattern::check(cx, expr, method_call.ident.name, args);
- unnecessary_to_owned::check(cx, expr, method_call.ident.name, args, self.msrv);
+ or_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args);
+ expect_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args);
+ clone_on_copy::check(cx, expr, method_call.ident.name, receiver, args);
+ clone_on_ref_ptr::check(cx, expr, method_call.ident.name, receiver, args);
+ inefficient_to_string::check(cx, expr, method_call.ident.name, receiver, args);
+ single_char_add_str::check(cx, expr, receiver, args);
+ into_iter_on_ref::check(cx, expr, method_span, method_call.ident.name, receiver);
+ single_char_pattern::check(cx, expr, method_call.ident.name, receiver, args);
+ unnecessary_to_owned::check(cx, expr, method_call.ident.name, receiver, args, self.msrv);
},
hir::ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => {
let mut info = BinaryExprInfo {
impl Methods {
#[allow(clippy::too_many_lines)]
fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- if let Some((name, [recv, args @ ..], span)) = method_call(expr) {
+ if let Some((name, recv, args, span)) = method_call(expr) {
match (name, args) {
("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [_arg]) => {
zst_offset::check(cx, expr, recv);
("assume_init", []) => uninit_assumed_init::check(cx, expr, recv),
("cloned", []) => cloned_instead_of_copied::check(cx, expr, recv, span, self.msrv),
("collect", []) => match method_call(recv) {
- Some((name @ ("cloned" | "copied"), [recv2], _)) => {
+ Some((name @ ("cloned" | "copied"), recv2, [], _)) => {
iter_cloned_collect::check(cx, name, expr, recv2);
},
- Some(("map", [m_recv, m_arg], _)) => {
+ Some(("map", m_recv, [m_arg], _)) => {
map_collect_result_unit::check(cx, expr, m_recv, m_arg, recv);
},
- Some(("take", [take_self_arg, take_arg], _)) => {
+ Some(("take", take_self_arg, [take_arg], _)) => {
if meets_msrv(self.msrv, msrvs::STR_REPEAT) {
manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg);
}
_ => {},
},
("count", []) if is_trait_method(cx, expr, sym::Iterator) => match method_call(recv) {
- Some(("cloned", [recv2], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, true, false),
- Some((name2 @ ("into_iter" | "iter" | "iter_mut"), [recv2], _)) => {
+ Some(("cloned", recv2, [], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, true, false),
+ Some((name2 @ ("into_iter" | "iter" | "iter_mut"), recv2, [], _)) => {
iter_count::check(cx, expr, recv2, name2);
},
- Some(("map", [_, arg], _)) => suspicious_map::check(cx, expr, recv, arg),
- Some(("filter", [recv2, arg], _)) => bytecount::check(cx, expr, recv2, arg),
- Some(("bytes", [recv2], _)) => bytes_count_to_len::check(cx, expr, recv, recv2),
+ Some(("map", _, [arg], _)) => suspicious_map::check(cx, expr, recv, arg),
+ Some(("filter", recv2, [arg], _)) => bytecount::check(cx, expr, recv2, arg),
+ Some(("bytes", recv2, [], _)) => bytes_count_to_len::check(cx, expr, recv, recv2),
_ => {},
},
("drain", [arg]) => {
iter_with_drain::check(cx, expr, recv, span, arg);
},
("ends_with", [arg]) => {
- if let ExprKind::MethodCall(_, _, span) = expr.kind {
+ if let ExprKind::MethodCall(.., span) = expr.kind {
case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg);
}
},
("expect", [_]) => match method_call(recv) {
- Some(("ok", [recv], _)) => ok_expect::check(cx, expr, recv),
- Some(("err", [recv], err_span)) => err_expect::check(cx, expr, recv, self.msrv, span, err_span),
+ Some(("ok", recv, [], _)) => ok_expect::check(cx, expr, recv),
+ Some(("err", recv, [], err_span)) => err_expect::check(cx, expr, recv, self.msrv, span, err_span),
_ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests),
},
("expect_err", [_]) => expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests),
flat_map_option::check(cx, expr, arg, span);
},
("flatten", []) => match method_call(recv) {
- Some(("map", [recv, map_arg], map_span)) => map_flatten::check(cx, expr, recv, map_arg, map_span),
- Some(("cloned", [recv2], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true),
+ Some(("map", recv, [map_arg], map_span)) => map_flatten::check(cx, expr, recv, map_arg, map_span),
+ Some(("cloned", recv2, [], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true),
_ => {},
},
("fold", [init, acc]) => unnecessary_fold::check(cx, expr, init, acc, span),
("for_each", [_]) => {
- if let Some(("inspect", [_, _], span2)) = method_call(recv) {
+ if let Some(("inspect", _, [_], span2)) = method_call(recv) {
inspect_for_each::check(cx, expr, span2);
}
},
iter_on_single_or_empty_collections::check(cx, expr, name, recv);
},
("join", [join_arg]) => {
- if let Some(("collect", _, span)) = method_call(recv) {
+ if let Some(("collect", _, _, span)) = method_call(recv) {
unnecessary_join::check(cx, expr, recv, join_arg, span);
}
},
("last", []) | ("skip", [_]) => {
- if let Some((name2, [recv2, args2 @ ..], _span2)) = method_call(recv) {
+ if let Some((name2, recv2, args2, _span2)) = method_call(recv) {
if let ("cloned", []) = (name2, args2) {
iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
}
} else {
map_err_ignore::check(cx, expr, m_arg);
}
- if let Some((name, [recv2, args @ ..], span2)) = method_call(recv) {
+ if let Some((name, recv2, args, span2)) = method_call(recv) {
match (name, args) {
("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, self.msrv),
("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, self.msrv),
manual_ok_or::check(cx, expr, recv, def, map);
},
("next", []) => {
- if let Some((name2, [recv2, args2 @ ..], _)) = method_call(recv) {
+ if let Some((name2, recv2, args2, _)) = method_call(recv) {
match (name2, args2) {
("cloned", []) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
("filter", [arg]) => filter_next::check(cx, expr, recv2, arg),
}
},
("nth", [n_arg]) => match method_call(recv) {
- Some(("bytes", [recv2], _)) => bytes_nth::check(cx, expr, recv2, n_arg),
- Some(("cloned", [recv2], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
- Some(("iter", [recv2], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false),
- Some(("iter_mut", [recv2], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true),
+ Some(("bytes", recv2, [], _)) => bytes_nth::check(cx, expr, recv2, n_arg),
+ Some(("cloned", recv2, [], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
+ Some(("iter", recv2, [], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false),
+ Some(("iter_mut", recv2, [], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true),
_ => iter_nth_zero::check(cx, expr, recv, n_arg),
},
("ok_or_else", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "ok_or"),
},
("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
("take", [_arg]) => {
- if let Some((name2, [recv2, args2 @ ..], _span2)) = method_call(recv) {
+ if let Some((name2, recv2, args2, _span2)) = method_call(recv) {
if let ("cloned", []) = (name2, args2) {
iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
}
},
("unwrap", []) => {
match method_call(recv) {
- Some(("get", [recv, get_arg], _)) => {
+ Some(("get", recv, [get_arg], _)) => {
get_unwrap::check(cx, expr, recv, get_arg, false);
},
- Some(("get_mut", [recv, get_arg], _)) => {
+ Some(("get_mut", recv, [get_arg], _)) => {
get_unwrap::check(cx, expr, recv, get_arg, true);
},
- Some(("or", [recv, or_arg], or_span)) => {
+ Some(("or", recv, [or_arg], or_span)) => {
or_then_unwrap::check(cx, expr, recv, or_arg, or_span);
},
_ => {},
},
("unwrap_err", []) => unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests),
("unwrap_or", [u_arg]) => match method_call(recv) {
- Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), [lhs, rhs], _)) => {
+ Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), lhs, [rhs], _)) => {
manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]);
},
- Some(("map", [m_recv, m_arg], span)) => {
+ Some(("map", m_recv, [m_arg], span)) => {
option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span);
},
- Some(("then_some", [t_recv, t_arg], _)) => {
+ Some(("then_some", t_recv, [t_arg], _)) => {
obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg);
},
_ => {},
},
("unwrap_or_else", [u_arg]) => match method_call(recv) {
- Some(("map", [recv, map_arg], _))
+ Some(("map", recv, [map_arg], _))
if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, self.msrv) => {},
_ => {
unwrap_or_else_default::check(cx, expr, recv, u_arg);
},
},
("zip", [arg]) => {
- if let ExprKind::MethodCall(name, [iter_recv], _) = recv.kind
+ if let ExprKind::MethodCall(name, iter_recv, [], _) = recv.kind
&& name.ident.name == sym::iter
{
range_zip_with_len::check(cx, expr, iter_recv, arg);
}
fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, is_some: bool) {
- if let Some((name @ ("find" | "position" | "rposition"), [f_recv, arg], span)) = method_call(recv) {
+ if let Some((name @ ("find" | "position" | "rposition"), f_recv, [arg], span)) = method_call(recv) {
search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span);
}
}
}
fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) {
- if let ExprKind::MethodCall(path, arguments, _) = argument.kind {
- let obj_ty = cx.typeck_results().expr_ty(&arguments[0]).peel_refs();
+ if let ExprKind::MethodCall(path, receiver, arguments, _) = argument.kind {
+ let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs();
// Only proceed if this is a call on some object of type std::fs::OpenOptions
- if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 {
- let argument_option = match arguments[1].kind {
+ if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 1 {
+ let argument_option = match arguments[0].kind {
ExprKind::Lit(ref span) => {
if let Spanned {
node: LitKind::Bool(lit),
_ => (),
}
- get_open_options(cx, &arguments[0], options);
+ get_open_options(cx, receiver, options);
}
}
}
let closure_expr = peel_blocks(&closure_body.value);
match &closure_expr.kind {
- hir::ExprKind::MethodCall(_, args, _) => {
+ hir::ExprKind::MethodCall(_, receiver, [], _) => {
if_chain! {
- if args.len() == 1;
- if path_to_local_id(&args[0], closure_body.params[0].pat.hir_id);
+ if path_to_local_id(receiver, closure_body.params[0].pat.hir_id);
let adj = cx
.typeck_results()
- .expr_adjustments(&args[0])
+ .expr_adjustments(receiver)
.iter()
.map(|x| &x.kind)
.collect::<Box<[_]>>();
expr: &hir::Expr<'_>,
method_span: Span,
name: &str,
+ receiver: &'tcx hir::Expr<'_>,
args: &'tcx [hir::Expr<'_>],
) {
/// Checks for `unwrap_or(T::new())` or `unwrap_or(T::default())`.
}
}
- if let [self_arg, arg] = args {
+ if let [arg] = args {
let inner_arg = if let hir::ExprKind::Block(
hir::Block {
stmts: [],
let or_has_args = !or_args.is_empty();
if !check_unwrap_or_default(cx, name, fun, arg, or_has_args, expr.span, method_span) {
let fun_span = if or_has_args { None } else { Some(fun.span) };
- check_general_case(cx, name, method_span, self_arg, arg, expr.span, fun_span);
+ check_general_case(cx, name, method_span, receiver, arg, expr.span, fun_span);
}
},
hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => {
- check_general_case(cx, name, method_span, self_arg, arg, expr.span, None);
+ check_general_case(cx, name, method_span, receiver, arg, expr.span, None);
},
_ => (),
}
if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::Range::hir(zip_arg);
if is_integer_const(cx, start, 0);
// `.len()` call
- if let ExprKind::MethodCall(len_path, [len_recv], _) = end.kind;
+ if let ExprKind::MethodCall(len_path, len_recv, [], _) = end.kind;
if len_path.ident.name == sym::len;
// `.iter()` and `.len()` called on same `Path`
if let ExprKind::Path(QPath::Resolved(_, iter_path)) = recv.kind;
use rustc_hir as hir;
use rustc_lint::LateContext;
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
if match_def_path(cx, fn_def_id, &paths::PUSH_STR) {
- single_char_push_string::check(cx, expr, args);
+ single_char_push_string::check(cx, expr, receiver, args);
} else if match_def_path(cx, fn_def_id, &paths::INSERT_STR) {
- single_char_insert_string::check(cx, expr, args);
+ single_char_insert_string::check(cx, expr, receiver, args);
}
}
}
use super::SINGLE_CHAR_ADD_STR;
/// lint for length-1 `str`s as argument for `insert_str`
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
let mut applicability = Applicability::MachineApplicable;
- if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[2], &mut applicability) {
+ if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) {
let base_string_snippet =
- snippet_with_applicability(cx, args[0].span.source_callsite(), "_", &mut applicability);
- let pos_arg = snippet_with_applicability(cx, args[1].span, "..", &mut applicability);
+ snippet_with_applicability(cx, receiver.span.source_callsite(), "_", &mut applicability);
+ let pos_arg = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);
let sugg = format!("{}.insert({}, {})", base_string_snippet, pos_arg, extension_string);
span_lint_and_sugg(
cx,
use super::SINGLE_CHAR_PATTERN;
const PATTERN_METHODS: [(&str, usize); 24] = [
- ("contains", 1),
- ("starts_with", 1),
- ("ends_with", 1),
- ("find", 1),
- ("rfind", 1),
- ("split", 1),
- ("split_inclusive", 1),
- ("rsplit", 1),
- ("split_terminator", 1),
- ("rsplit_terminator", 1),
- ("splitn", 2),
- ("rsplitn", 2),
- ("split_once", 1),
- ("rsplit_once", 1),
- ("matches", 1),
- ("rmatches", 1),
- ("match_indices", 1),
- ("rmatch_indices", 1),
- ("strip_prefix", 1),
- ("strip_suffix", 1),
- ("trim_start_matches", 1),
- ("trim_end_matches", 1),
- ("replace", 1),
- ("replacen", 1),
+ ("contains", 0),
+ ("starts_with", 0),
+ ("ends_with", 0),
+ ("find", 0),
+ ("rfind", 0),
+ ("split", 0),
+ ("split_inclusive", 0),
+ ("rsplit", 0),
+ ("split_terminator", 0),
+ ("rsplit_terminator", 0),
+ ("splitn", 1),
+ ("rsplitn", 1),
+ ("split_once", 0),
+ ("rsplit_once", 0),
+ ("matches", 0),
+ ("rmatches", 0),
+ ("match_indices", 0),
+ ("rmatch_indices", 0),
+ ("strip_prefix", 0),
+ ("strip_suffix", 0),
+ ("trim_start_matches", 0),
+ ("trim_end_matches", 0),
+ ("replace", 0),
+ ("replacen", 0),
];
/// lint for length-1 `str`s for methods in `PATTERN_METHODS`
-pub(super) fn check(cx: &LateContext<'_>, _expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
+pub(super) fn check(
+ cx: &LateContext<'_>,
+ _expr: &hir::Expr<'_>,
+ method_name: Symbol,
+ receiver: &hir::Expr<'_>,
+ args: &[hir::Expr<'_>],
+) {
for &(method, pos) in &PATTERN_METHODS {
if_chain! {
- if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(&args[0]).kind();
+ if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(receiver).kind();
if *ty.kind() == ty::Str;
if method_name.as_str() == method && args.len() > pos;
let arg = &args[pos];
use super::SINGLE_CHAR_ADD_STR;
/// lint for length-1 `str`s as argument for `push_str`
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
let mut applicability = Applicability::MachineApplicable;
- if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) {
+ if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[0], &mut applicability) {
let base_string_snippet =
- snippet_with_applicability(cx, args[0].span.source_callsite(), "..", &mut applicability);
+ snippet_with_applicability(cx, receiver.span.source_callsite(), "..", &mut applicability);
let sugg = format!("{}.push({})", base_string_snippet, extension_string);
span_lint_and_sugg(
cx,
) -> Option<IterUsage> {
let (kind, span) = match iter.next() {
Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => {
- let (name, args) = if let ExprKind::MethodCall(name, [_, args @ ..], _) = e.kind {
+ let (name, args) = if let ExprKind::MethodCall(name, _, [args @ ..], _) = e.kind {
(name, args)
} else {
return None;
} else {
if_chain! {
if let Some((_, Node::Expr(next_expr))) = iter.next();
- if let ExprKind::MethodCall(next_name, [_], _) = next_expr.kind;
+ if let ExprKind::MethodCall(next_name, _, [], _) = next_expr.kind;
if next_name.ident.name == sym::next;
if next_expr.span.ctxt() == ctxt;
if let Some(next_id) = cx.typeck_results().type_dependent_def_id(next_expr.hir_id);
}
},
_ if e.span.ctxt() != ctxt => (None, span),
- ExprKind::MethodCall(name, [_], _)
+ ExprKind::MethodCall(name, _, [], _)
if name.ident.name == sym::unwrap
&& cx
.typeck_results()
return;
}
if let Some(arglists) = method_chain_args(arg, &["chars"]) {
- let target = &arglists[0][0];
+ let target = &arglists[0].0;
let self_ty = cx.typeck_results().expr_ty(target).peel_refs();
let ref_str = if *self_ty.kind() == ty::Str {
""
if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
then {
let snippet = if_chain! {
- if let ExprKind::MethodCall(maybe_iter_method_name, [collection], _) = receiver.kind;
+ if let ExprKind::MethodCall(maybe_iter_method_name, collection, [], _) = receiver.kind;
if maybe_iter_method_name.ident.name == sym::iter;
if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
// This is a duplicate of what's happening in clippy_lints::methods::method_call,
// which isn't ideal, We want to get the method call span,
// but prefer to avoid changing the signature of the function itself.
- if let hir::ExprKind::MethodCall(_, _, span) = expr.kind {
+ if let hir::ExprKind::MethodCall(.., span) = expr.kind {
span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| {
diag.span_suggestion(
span,
// The two exprs are method calls.
// Check to see that the function is the same and the arguments are mirrored
// This is enough because the receiver of the method is listed in the arguments
- (ExprKind::MethodCall(left_segment, left_args, _), ExprKind::MethodCall(right_segment, right_args, _)) => {
+ (
+ ExprKind::MethodCall(left_segment, left_receiver, left_args, _),
+ ExprKind::MethodCall(right_segment, right_receiver, right_args, _),
+ ) => {
left_segment.ident == right_segment.ident
&& iter::zip(*left_args, *right_args).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident))
+ && mirrored_exprs(left_receiver, a_ident, right_receiver, b_ident)
},
// Two tuples with mirrored contents
(ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => {
Param { pat: Pat { kind: PatKind::Binding(_, _, left_ident, _), .. }, ..},
Param { pat: Pat { kind: PatKind::Binding(_, _, right_ident, _), .. }, .. }
] = &closure_body.params;
- if let ExprKind::MethodCall(method_path, [left_expr, right_expr], _) = closure_body.value.kind;
+ if let ExprKind::MethodCall(method_path, left_expr, [right_expr], _) = closure_body.value.kind;
if method_path.ident.name == sym::cmp;
if is_trait_method(cx, &closure_body.value, sym::Ord);
then {
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'tcx>,
method_name: Symbol,
- args: &'tcx [Expr<'tcx>],
+ receiver: &'tcx Expr<'_>,
+ args: &'tcx [Expr<'_>],
msrv: Option<RustcVersion>,
) {
if_chain! {
if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
- if let [receiver] = args;
+ if args.is_empty();
then {
if is_cloned_or_copied(cx, method_name, method_def_id) {
unnecessary_iter_cloned::check(cx, expr, method_name, receiver);
) -> bool {
if_chain! {
if let Some((maybe_call, maybe_arg)) = skip_addr_of_ancestors(cx, expr);
- if let Some((callee_def_id, call_substs, call_args)) = get_callee_substs_and_args(cx, maybe_call);
+ if let Some((callee_def_id, call_substs, call_receiver, call_args)) = get_callee_substs_and_args(cx, maybe_call);
let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
- if let Some(i) = call_args.iter().position(|arg| arg.hir_id == maybe_arg.hir_id);
+ let index = if let Some(call_receiver) = call_receiver {
+ std::iter::once(call_receiver).chain(call_args.iter()).position(|arg| arg.hir_id == maybe_arg.hir_id)
+ } else {
+ call_args.iter().position(|arg| arg.hir_id == maybe_arg.hir_id)
+ };
+ if let Some(i) = index;
if let Some(input) = fn_sig.inputs().get(i);
let (input, n_refs) = peel_mid_ty_refs(*input);
if let (trait_predicates, projection_predicates) = get_input_traits_and_projections(cx, callee_def_id, input);
fn get_callee_substs_and_args<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'tcx>,
-) -> Option<(DefId, SubstsRef<'tcx>, &'tcx [Expr<'tcx>])> {
+) -> Option<(DefId, SubstsRef<'tcx>, Option<&'tcx Expr<'tcx>>, &'tcx [Expr<'tcx>])> {
if_chain! {
if let ExprKind::Call(callee, args) = expr.kind;
let callee_ty = cx.typeck_results().expr_ty(callee);
if let ty::FnDef(callee_def_id, _) = callee_ty.kind();
then {
let substs = cx.typeck_results().node_substs(callee.hir_id);
- return Some((*callee_def_id, substs, args));
+ return Some((*callee_def_id, substs, None, args));
}
}
if_chain! {
- if let ExprKind::MethodCall(_, args, _) = expr.kind;
+ if let ExprKind::MethodCall(_, receiver, args, _) = expr.kind;
if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
then {
let substs = cx.typeck_results().node_substs(expr.hir_id);
- return Some((method_def_id, substs, args));
+ return Some((method_def_id, substs, Some(receiver), args));
}
}
None
}
}
- if let hir::ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind {
+ if let hir::ExprKind::MethodCall(path, self_arg, ..) = &expr.kind {
if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(self_arg)) {
Some(self_arg)
} else {
self.addr_of_exprs.push(parent);
return;
},
- ExprKind::MethodCall(_, args, _) => {
+ ExprKind::MethodCall(.., args, _) => {
if_chain! {
- if args.iter().skip(1).all(|arg| !self.is_binding(arg));
+ if args.iter().all(|arg| !self.is_binding(arg));
if let Some(method_def_id) = self.cx.typeck_results().type_dependent_def_id(parent.hir_id);
let method_ty = self.cx.tcx.type_of(method_def_id);
let self_ty = method_ty.fn_sig(self.cx.tcx).input(0).skip_binder();
.qpath_res(qpath, path.hir_id)
.opt_def_id()
.and_then(|def_id| match cx.tcx.get_diagnostic_name(def_id) {
- Some(sym::cmp_min) => fetch_const(cx, args, MinMax::Min),
- Some(sym::cmp_max) => fetch_const(cx, args, MinMax::Max),
+ Some(sym::cmp_min) => fetch_const(cx, None, args, MinMax::Min),
+ Some(sym::cmp_max) => fetch_const(cx, None, args, MinMax::Max),
_ => None,
})
} else {
None
}
},
- ExprKind::MethodCall(path, args, _) => {
+ ExprKind::MethodCall(path, receiver, args @ [_], _) => {
if_chain! {
- if let [obj, _] = args;
- if cx.typeck_results().expr_ty(obj).is_floating_point() || match_trait_method(cx, expr, &paths::ORD);
+ if cx.typeck_results().expr_ty(receiver).is_floating_point() || match_trait_method(cx, expr, &paths::ORD);
then {
if path.ident.name == sym!(max) {
- fetch_const(cx, args, MinMax::Max)
+ fetch_const(cx, Some(receiver), args, MinMax::Max)
} else if path.ident.name == sym!(min) {
- fetch_const(cx, args, MinMax::Min)
+ fetch_const(cx, Some(receiver), args, MinMax::Min)
} else {
None
}
}
}
-fn fetch_const<'a>(cx: &LateContext<'_>, args: &'a [Expr<'a>], m: MinMax) -> Option<(MinMax, Constant, &'a Expr<'a>)> {
- if args.len() != 2 {
+fn fetch_const<'a>(
+ cx: &LateContext<'_>,
+ receiver: Option<&'a Expr<'a>>,
+ args: &'a [Expr<'a>],
+ m: MinMax,
+) -> Option<(MinMax, Constant, &'a Expr<'a>)> {
+ let mut args = receiver.into_iter().chain(args.into_iter());
+ let arg0 = args.next()?;
+ let arg1 = args.next()?;
+ if args.next().is_some() {
return None;
}
- constant_simple(cx, cx.typeck_results(), &args[0]).map_or_else(
- || constant_simple(cx, cx.typeck_results(), &args[1]).map(|c| (m, c, &args[0])),
+ constant_simple(cx, cx.typeck_results(), arg0).map_or_else(
+ || constant_simple(cx, cx.typeck_results(), arg1).map(|c| (m, c, arg0)),
|c| {
- if constant_simple(cx, cx.typeck_results(), &args[1]).is_none() {
+ if constant_simple(cx, cx.typeck_results(), arg1).is_none() {
// otherwise ignore
- Some((m, c, &args[1]))
+ Some((m, c, arg1))
} else {
None
}
if let ExprKind::Path(ref path) = fn_expr.kind {
check_arguments(
cx,
- arguments,
+ arguments.iter().collect(),
cx.typeck_results().expr_ty(fn_expr),
&rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)),
"function",
);
}
},
- ExprKind::MethodCall(path, arguments, _) => {
+ ExprKind::MethodCall(path, receiver, arguments, _) => {
let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap();
let substs = cx.typeck_results().node_substs(e.hir_id);
let method_type = cx.tcx.bound_type_of(def_id).subst(cx.tcx, substs);
- check_arguments(cx, arguments, method_type, path.ident.as_str(), "method");
+ check_arguments(
+ cx,
+ std::iter::once(receiver).chain(arguments.iter()).collect(),
+ method_type,
+ path.ident.as_str(),
+ "method",
+ );
},
_ => (),
}
fn check_arguments<'tcx>(
cx: &LateContext<'tcx>,
- arguments: &[Expr<'_>],
+ arguments: Vec<&Expr<'_>>,
type_definition: Ty<'tcx>,
name: &str,
fn_kind: &str,
if_chain! {
// Check the method name is `for_each`.
- if let ExprKind::MethodCall(method_name, [for_each_recv, for_each_arg], _) = expr.kind;
+ if let ExprKind::MethodCall(method_name, for_each_recv, [for_each_arg], _) = expr.kind;
if method_name.ident.name == Symbol::intern("for_each");
// Check `for_each` is an associated function of `Iterator`.
if is_trait_method(cx, expr, sym::Iterator);
// Checks the receiver of `for_each` is also a method call.
- if let ExprKind::MethodCall(_, [iter_recv], _) = for_each_recv.kind;
+ if let ExprKind::MethodCall(_, iter_recv, [], _) = for_each_recv.kind;
// Skip the lint if the call chain is too long. e.g. `v.field.iter().for_each()` or
// `v.foo().iter().for_each()` must be skipped.
if matches!(
impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
match &expr.kind {
- ExprKind::MethodCall(path, [func, param], _) => {
+ ExprKind::MethodCall(path, func, [param], _) => {
let obj_ty = cx.typeck_results().expr_ty(func).peel_refs();
if_chain! {
}
return;
},
- ExprKind::MethodCall(_, args, _)
+ ExprKind::MethodCall(_, receiver, args, _)
if typeck.type_dependent_def_id(parent.hir_id).map_or(false, |id| {
id == param.fn_id
&& has_matching_substs(param.fn_kind, typeck.node_substs(parent.hir_id))
}) =>
{
- if let Some(idx) = args.iter().position(|arg| arg.hir_id == child_id) {
+ if let Some(idx) = std::iter::once(receiver).chain(args.iter()).position(|arg| arg.hir_id == child_id) {
param.uses.push(Usage::new(span, idx));
}
return;
fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) {
let typeck = cx.typeck_results();
let (arg, arg_span) = match expr.kind {
- ExprKind::MethodCall(.., [arg], _)
+ ExprKind::MethodCall(_, arg, [], _)
if typeck
.type_dependent_def_id(expr.hir_id)
.and_then(|id| cx.tcx.trait_of_item(id))
right: &'tcx Expr<'_>,
) {
if op == BinOpKind::Div
- && let ExprKind::MethodCall(method_path, [self_arg], _) = left.kind
+ && let ExprKind::MethodCall(method_path, self_arg, [], _) = left.kind
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration)
&& let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right)
{
}
if_chain! {
- if let ExprKind::MethodCall(method_name, [ref self_arg, ..], _) = expr.kind;
+ if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind;
if sym!(signum) == method_name.ident.name;
// Check that the receiver of the signum() is a float (expressions[0] is the receiver of
// the method call)
if let ItemKind::Impl(item) = &item.kind;
if let Some(of_trait) = &item.of_trait;
if let Some(seg) = of_trait.path.segments.last();
- if let Some(Res::Def(_, trait_id)) = seg.res;
+ if let Res::Def(_, trait_id) = seg.res;
if trait_id == bin_op;
if let Some(generic_args) = seg.args;
if let Some(GenericArg::Type(other_ty)) = generic_args.args.last();
set_skip_flag();
}
},
- ExprKind::MethodCall(name, expr_args @ [self_arg, ..], _) => {
- let i = expr_args.iter().position(|arg| arg.hir_id == child_id).unwrap_or(0);
+ ExprKind::MethodCall(name, self_arg, expr_args, _) => {
+ let i = std::iter::once(self_arg)
+ .chain(expr_args.iter())
+ .position(|arg| arg.hir_id == child_id)
+ .unwrap_or(0);
if i == 0 {
// Check if the method can be renamed.
let name = name.ident.as_str();
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> {
- if let ExprKind::MethodCall(path_segment, [arg_0, arg_1, ..], _) = &expr.kind {
+ if let ExprKind::MethodCall(path_segment, arg_0, [arg_1, ..], _) = &expr.kind {
if is_expr_ty_raw_ptr(cx, arg_0) {
if path_segment.ident.name == sym::offset {
return Some((arg_0, arg_1, Method::Offset));
if_chain! {
if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr);
if !is_else_clause(cx.tcx, expr);
- if let ExprKind::MethodCall(segment, [caller, ..], _) = &cond.kind;
+ if let ExprKind::MethodCall(segment, caller, ..) = &cond.kind;
let caller_ty = cx.typeck_results().expr_ty(caller);
let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else);
if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block);
// finds use of `_.read(&mut v)`
let mut read_found = false;
let mut visitor = expr_visitor_no_bodies(|expr| {
- if let ExprKind::MethodCall(path, [_self, arg], _) = expr.kind
+ if let ExprKind::MethodCall(path, _self, [arg], _) = expr.kind
&& let PathSegment { ident: read_or_read_exact, .. } = *path
&& matches!(read_or_read_exact.as_str(), "read" | "read_exact")
&& let ExprKind::AddrOf(_, hir::Mutability::Mut, inner) = arg.kind
if mut_ty.mutbl == Mutability::Not;
if let TyKind::Path(ref qpath) = &mut_ty.ty.kind;
let last = last_path_segment(qpath);
- if let Some(res) = last.res;
- if let Some(def_id) = res.opt_def_id();
+ if let Some(def_id) = last.res.opt_def_id();
if cx.tcx.is_diagnostic_item(sym::Option, def_id);
if let Some(params) = last_path_segment(qpath).args ;
};
if_chain! {
// Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods
- if let ExprKind::MethodCall(method_path, [ptr_self, .., count], _) = expr.kind;
+ if let ExprKind::MethodCall(method_path, ptr_self, [.., count], _) = expr.kind;
let method_ident = method_path.ident.as_str();
if METHODS.iter().any(|m| *m == method_ident);
fn search_slow_extend_filling(&mut self, expr: &'tcx Expr<'_>) {
if_chain! {
if self.initialization_found;
- if let ExprKind::MethodCall(path, [self_arg, extend_arg], _) = expr.kind;
+ if let ExprKind::MethodCall(path, self_arg, [extend_arg], _) = expr.kind;
if path_to_local_id(self_arg, self.vec_alloc.local_id);
if path.ident.name == sym!(extend);
if self.is_repeat_take(extend_arg);
/// Checks if the given expression is resizing a vector with 0
fn search_slow_resize_filling(&mut self, expr: &'tcx Expr<'_>) {
if self.initialization_found
- && let ExprKind::MethodCall(path, [self_arg, len_arg, fill_arg], _) = expr.kind
+ && let ExprKind::MethodCall(path, self_arg, [len_arg, fill_arg], _) = expr.kind
&& path_to_local_id(self_arg, self.vec_alloc.local_id)
&& path.ident.name == sym!(resize)
// Check that is filled with 0
// Check that len expression is equals to `with_capacity` expression
if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr) {
self.slow_expression = Some(InitializationType::Resize(expr));
- } else if let ExprKind::MethodCall(path, _, _) = len_arg.kind && path.ident.as_str() == "capacity" {
+ } else if let ExprKind::MethodCall(path, ..) = len_arg.kind && path.ident.as_str() == "capacity" {
self.slow_expression = Some(InitializationType::Resize(expr));
}
}
/// Returns `true` if give expression is `repeat(0).take(...)`
fn is_repeat_take(&self, expr: &Expr<'_>) -> bool {
if_chain! {
- if let ExprKind::MethodCall(take_path, [recv, len_arg, ..], _) = expr.kind;
+ if let ExprKind::MethodCall(take_path, recv, [len_arg, ..], _) = expr.kind;
if take_path.ident.name == sym!(take);
// Check that take is applied to `repeat(0)`
if self.is_repeat_zero(recv);
// Check that len expression is equals to `with_capacity` expression
if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr) {
return true;
- } else if let ExprKind::MethodCall(path, _, _) = len_arg.kind && path.ident.as_str() == "capacity" {
+ } else if let ExprKind::MethodCall(path, ..) = len_arg.kind && path.ident.as_str() == "capacity" {
return true;
}
}
let (method_names, expressions, _) = method_calls(left, 1);
if method_names.len() == 1;
if expressions.len() == 1;
- if expressions[0].len() == 1;
+ if expressions[0].1.is_empty();
if method_names[0] == sym!(as_bytes);
// Check for slicer
then {
let mut applicability = Applicability::MachineApplicable;
- let string_expression = &expressions[0][0];
+ let string_expression = &expressions[0].0;
let snippet_app = snippet_with_applicability(
cx,
}
if_chain! {
- if let ExprKind::MethodCall(path, args, _) = &e.kind;
+ if let ExprKind::MethodCall(path, receiver, ..) = &e.kind;
if path.ident.name == sym!(as_bytes);
- if let ExprKind::Lit(lit) = &args[0].kind;
+ if let ExprKind::Lit(lit) = &receiver.kind;
if let LitKind::Str(lit_content, _) = &lit.node;
then {
- let callsite = snippet(cx, args[0].span.source_callsite(), r#""foo""#);
+ let callsite = snippet(cx, receiver.span.source_callsite(), r#""foo""#);
let mut applicability = Applicability::MachineApplicable;
if callsite.starts_with("include_str!") {
span_lint_and_sugg(
e.span,
"calling `as_bytes()` on `include_str!(..)`",
"consider using `include_bytes!(..)` instead",
- snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability).replacen(
+ snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability).replacen(
"include_str",
"include_bytes",
1,
);
} else if lit_content.as_str().is_ascii()
&& lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT
- && !args[0].span.from_expansion()
+ && !receiver.span.from_expansion()
{
span_lint_and_sugg(
cx,
"consider using a byte string literal instead",
format!(
"b{}",
- snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability)
+ snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability)
),
applicability,
);
}
if_chain! {
- if let ExprKind::MethodCall(path, [recv], _) = &e.kind;
+ if let ExprKind::MethodCall(path, recv, [], _) = &e.kind;
if path.ident.name == sym!(into_bytes);
- if let ExprKind::MethodCall(path, [recv], _) = &recv.kind;
+ if let ExprKind::MethodCall(path, recv, [], _) = &recv.kind;
if matches!(path.ident.name.as_str(), "to_owned" | "to_string");
if let ExprKind::Lit(lit) = &recv.kind;
if let LitKind::Str(lit_content, _) = &lit.node;
impl<'tcx> LateLintPass<'tcx> for StrToString {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
if_chain! {
- if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
+ if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind;
if path.ident.name == sym::to_string;
let ty = cx.typeck_results().expr_ty(self_arg);
if let ty::Ref(_, ty, ..) = ty.kind();
impl<'tcx> LateLintPass<'tcx> for StringToString {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
if_chain! {
- if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
+ if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind;
if path.ident.name == sym::to_string;
let ty = cx.typeck_results().expr_ty(self_arg);
if is_type_diagnostic_item(cx, ty, sym::String);
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
let tyckres = cx.typeck_results();
if_chain! {
- if let ExprKind::MethodCall(path, [split_recv], split_ws_span) = expr.kind;
+ if let ExprKind::MethodCall(path, split_recv, [], split_ws_span) = expr.kind;
if path.ident.name == sym!(split_whitespace);
if let Some(split_ws_def_id) = tyckres.type_dependent_def_id(expr.hir_id);
if cx.tcx.is_diagnostic_item(sym::str_split_whitespace, split_ws_def_id);
- if let ExprKind::MethodCall(path, [_trim_recv], trim_span) = split_recv.kind;
+ if let ExprKind::MethodCall(path, _trim_recv, [], trim_span) = split_recv.kind;
if let trim_fn_name @ ("trim" | "trim_start" | "trim_end") = path.ident.name.as_str();
if let Some(trim_def_id) = tyckres.type_dependent_def_id(split_recv.hir_id);
if is_one_of_trim_diagnostic_items(cx, trim_def_id);
if let ExprKind::Path(path) = &func.kind;
if let Some(did) = cx.qpath_res(path, func.hir_id).opt_def_id();
if match_libc_symbol(cx, did, "strlen");
- if let ExprKind::MethodCall(path, [self_arg], _) = recv.kind;
+ if let ExprKind::MethodCall(path, self_arg, [], _) = recv.kind;
if !recv.span.from_expansion();
if path.ident.name == sym::as_ptr;
then {
impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
if_chain! {
- if let hir::ExprKind::MethodCall(is_some_path, is_some_args, _) = &expr.kind;
+ if let hir::ExprKind::MethodCall(is_some_path, to_digit_expr, [], _) = &expr.kind;
if is_some_path.ident.name.as_str() == "is_some";
- if let [to_digit_expr] = &**is_some_args;
then {
let match_result = match &to_digit_expr.kind {
- hir::ExprKind::MethodCall(to_digits_path, to_digit_args, _) => {
+ hir::ExprKind::MethodCall(to_digits_path, char_arg, [radix_arg], _) => {
if_chain! {
- if let [char_arg, radix_arg] = &**to_digit_args;
if to_digits_path.ident.name.as_str() == "to_digit";
let char_arg_ty = cx.typeck_results().expr_ty_adjusted(char_arg);
if *char_arg_ty.kind() == ty::Char;
then {
- Some((true, char_arg, radix_arg))
+ Some((true, *char_arg, radix_arg))
} else {
None
}
}
hir::ExprKind::Call(to_digits_call, to_digit_args) => {
if_chain! {
- if let [char_arg, radix_arg] = &**to_digit_args;
+ if let [char_arg, radix_arg] = *to_digit_args;
if let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind;
if let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id);
if let Some(to_digits_def_id) = to_digits_call_res.opt_def_id();
if !bound_predicate.span.from_expansion();
if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
if let Some(PathSegment {
- res: Some(Res::SelfTy{ trait_: Some(def_id), alias_to: _ }), ..
+ res: Res::SelfTy{ trait_: Some(def_id), alias_to: _ }, ..
}) = segments.first();
if let Some(
Node::Item(
});
}
},
- ExprKind::MethodCall(path, [self_expr, _], _) if is_reserve(cx, path, self_expr) => {
+ ExprKind::MethodCall(path, self_expr, [_], _) if is_reserve(cx, path, self_expr) => {
return Some(TargetVec {
location: VecLocation::Expr(self_expr),
init_kind: None,
}
});
match expr.kind {
- ExprKind::MethodCall(path, [self_expr, _], _) => {
+ ExprKind::MethodCall(path, self_expr, [_], _) => {
let self_type = cx.typeck_results().expr_ty(self_expr).peel_refs();
if is_type_diagnostic_item(cx, self_type, sym::Vec) && path.ident.name.as_str() == "set_len" {
Some((self_expr, expr.span))
impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
- if let ExprKind::MethodCall(_, args, _) = expr.kind {
+ if let ExprKind::MethodCall(_, receiver, args, _) = expr.kind {
let arg_indices = get_args_to_check(cx, expr);
+ let args = std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>();
for (i, trait_name) in arg_indices {
if i < args.len() {
match check_arg(cx, &args[i]) {
locals_to_check: &mut Vec<HirId>,
seen_locals: &mut HirIdSet,
) -> bool {
- let (id, args) = match e.kind {
+ let (id, receiver, args) = match e.kind {
ExprKind::Call(
Expr {
kind: ExprKind::Path(ref path),
},
args,
) => match cx.qpath_res(path, *hir_id) {
- Res::Def(DefKind::AssocFn | DefKind::Fn, id) => (id, args),
+ Res::Def(DefKind::AssocFn | DefKind::Fn, id) => (id, None, args),
_ => return false,
},
- ExprKind::MethodCall(_, args, _) => match cx.typeck_results().type_dependent_def_id(e.hir_id) {
- Some(id) => (id, args),
+ ExprKind::MethodCall(_, receiver, args, _) => match cx.typeck_results().type_dependent_def_id(e.hir_id) {
+ Some(id) => (id, Some(receiver), args),
None => return false,
},
ExprKind::Path(QPath::Resolved(None, path)) => {
};
let sig = cx.tcx.fn_sig(id).skip_binder();
if let ty::Param(output_ty) = *sig.output().kind() {
+ let args: Vec<&Expr<'_>> = if let Some(receiver) = receiver {
+ std::iter::once(receiver).chain(args.iter()).collect()
+ } else {
+ args.iter().collect()
+ };
sig.inputs().iter().zip(args).all(|(&ty, arg)| {
!ty.is_param(output_ty.index) || each_value_source_needs_inference(cx, arg, locals_to_check, seen_locals)
})
}
}
- match expr.kind {
- ExprKind::Call(_, args) | ExprKind::MethodCall(_, args, _) => {
- let args_to_recover = args
- .iter()
- .filter(|arg| {
- if cx.typeck_results().expr_ty(arg).is_unit() && !utils::is_unit_literal(arg) {
- !matches!(
- &arg.kind,
- ExprKind::Match(.., MatchSource::TryDesugar) | ExprKind::Path(..)
- )
- } else {
- false
- }
- })
- .collect::<Vec<_>>();
- if !args_to_recover.is_empty() && !is_from_proc_macro(cx, expr) {
- lint_unit_args(cx, expr, &args_to_recover);
+ let args: Vec<_> = match expr.kind {
+ ExprKind::Call(_, args) => args.iter().collect(),
+ ExprKind::MethodCall(_, receiver, args, _) => std::iter::once(receiver).chain(args.iter()).collect(),
+ _ => return,
+ };
+
+ let args_to_recover = args
+ .into_iter()
+ .filter(|arg| {
+ if cx.typeck_results().expr_ty(arg).is_unit() && !utils::is_unit_literal(arg) {
+ !matches!(
+ &arg.kind,
+ ExprKind::Match(.., MatchSource::TryDesugar) | ExprKind::Path(..)
+ )
+ } else {
+ false
}
- },
- _ => (),
+ })
+ .collect::<Vec<_>>();
+ if !args_to_recover.is_empty() && !is_from_proc_macro(cx, expr) {
+ lint_unit_args(cx, expr, &args_to_recover.as_slice());
}
}
check_map_error(cx, res, expr);
}
},
- hir::ExprKind::MethodCall(path, [ref arg_0, ..], _) => match path.ident.as_str() {
+ hir::ExprKind::MethodCall(path, arg_0, ..) => match path.ident.as_str() {
"expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => {
check_map_error(cx, arg_0, expr);
},
fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) {
let mut call = call;
- while let hir::ExprKind::MethodCall(path, args, _) = call.kind {
+ while let hir::ExprKind::MethodCall(path, receiver, ..) = call.kind {
if matches!(path.ident.as_str(), "or" | "or_else" | "ok") {
- call = &args[0];
+ call = receiver;
} else {
break;
}
}
fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>, is_await: bool) {
- if let hir::ExprKind::MethodCall(path, _, _) = call.kind {
+ if let hir::ExprKind::MethodCall(path, ..) = call.kind {
let symbol = path.ident.as_str();
let read_trait = if is_await {
match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCREADEXT)
ident: method_name_ident,
..
},
- [self_arg, remaining_args @ ..],
+ self_arg,
+ remaining_args,
_,
) => {
let method_name = method_name_ident.name.as_str();
return collect_unwrap_info(cx, if_expr, expr, branch, !invert, false);
} else {
if_chain! {
- if let ExprKind::MethodCall(method_name, args, _) = &expr.kind;
- if let Some(local_id) = path_to_local(&args[0]);
- let ty = cx.typeck_results().expr_ty(&args[0]);
+ if let ExprKind::MethodCall(method_name, receiver, args, _) = &expr.kind;
+ if let Some(local_id) = path_to_local(receiver);
+ let ty = cx.typeck_results().expr_ty(receiver);
let name = method_name.ident.as_str();
if is_relevant_option_call(cx, ty, name) || is_relevant_result_call(cx, ty, name);
then {
- assert!(args.len() == 1);
+ assert!(args.len() == 0);
let unwrappable = match name {
"is_some" | "is_ok" => true,
"is_err" | "is_none" => false,
} else {
// find `unwrap[_err]()` calls:
if_chain! {
- if let ExprKind::MethodCall(method_name, [self_arg, ..], _) = expr.kind;
+ if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind;
if let Some(id) = path_to_local(self_arg);
if [sym::unwrap, sym::expect, sym!(unwrap_err)].contains(&method_name.ident.name);
let call_to_unwrap = [sym::unwrap, sym::expect].contains(&method_name.ident.name);
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
// check for `expect`
if let Some(arglists) = method_chain_args(expr, &["expect"]) {
- let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
+ let receiver_ty = self.typeck_results.expr_ty(&arglists[0].0).peel_refs();
if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option)
|| is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result)
{
// check for `unwrap`
if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
- let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
+ let receiver_ty = self.typeck_results.expr_ty(&arglists[0].0).peel_refs();
if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option)
|| is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result)
{
}
},
- ExprKind::MethodCall(name, .., [recv, ..], _) => {
+ ExprKind::MethodCall(name, recv, ..) => {
if is_trait_method(cx, e, sym::Into) && name.ident.as_str() == "into" {
let a = cx.typeck_results().expr_ty(e);
let b = cx.typeck_results().expr_ty(recv);
self.expr(func);
self.slice(args, |e| self.expr(e));
},
- ExprKind::MethodCall(method_name, args, _) => {
- bind!(self, method_name, args);
- kind!("MethodCall({method_name}, {args}, _)");
+ ExprKind::MethodCall(method_name, receiver, args, _) => {
+ bind!(self, method_name, receiver, args);
+ kind!("MethodCall({method_name}, {receiver}, {args}, _)");
self.ident(field!(method_name.ident));
+ self.expr(receiver);
self.slice(args, |e| self.expr(e));
},
ExprKind::Tup(elements) => {
}
fn body(&self, body_id: &Binding<hir::BodyId>) {
- let expr = &self.cx.tcx.hir().body(body_id.value).value;
+ let expr = self.cx.tcx.hir().body(body_id.value).value;
bind!(self, expr);
out!("let {expr} = &cx.tcx.hir().body({body_id}).value;");
self.expr(expr);
if let ["expn_data", "outer_expn"] = method_names.as_slice();
let args = arg_lists[1];
if args.len() == 1;
- let self_arg = &args[0];
+ let self_arg = &args.0;
let self_ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
if match_type(cx, self_ty, &paths::SYNTAX_CONTEXT);
then {
|| get_parent_expr(cx, last_place)
.map_or(false, |e| matches!(e.kind, ExprKind::AddrOf(_, Mutability::Mut, _)));
},
- ExprKind::MethodCall(_, [recv, ..], _)
+ ExprKind::MethodCall(_, recv, ..)
if recv.hir_id == e.hir_id
&& adjusted_mut == Mutability::Mut
&& !adjusted_ty.peel_refs().is_slice() =>
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
if let Some(searcher) = self.searcher.take() {
if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind
- && let ExprKind::MethodCall(name, [self_arg, _], _) = expr.kind
+ && let ExprKind::MethodCall(name, self_arg, [_], _) = expr.kind
&& path_to_local_id(self_arg, searcher.local_id)
&& name.ident.as_str() == "push"
{
ExprKind::Unary(UnOp::Neg, e) => (Pat::Str("-"), expr_search_pat(tcx, e).1),
ExprKind::Lit(ref lit) => lit_search_pat(&lit.node),
ExprKind::Array(_) | ExprKind::Repeat(..) => (Pat::Str("["), Pat::Str("]")),
- ExprKind::Call(e, []) | ExprKind::MethodCall(_, [e], _) => (expr_search_pat(tcx, e).0, Pat::Str("(")),
+ ExprKind::Call(e, []) | ExprKind::MethodCall(_, e, [], _) => (expr_search_pat(tcx, e).0, Pat::Str("(")),
ExprKind::Call(first, [.., last])
- | ExprKind::MethodCall(_, [first, .., last], _)
+ | ExprKind::MethodCall(_, first, [.., last], _)
| ExprKind::Binary(_, first, last)
| ExprKind::Tup([first, .., last])
| ExprKind::Assign(first, last, _)
});
}
-pub fn span_lint_hir(
- cx: &LateContext<'_>,
- lint: &'static Lint,
- hir_id: HirId,
- sp: Span,
- msg: &str,
-) {
+pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) {
cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |diag| {
let mut diag = diag.build(msg);
docs_link(&mut diag, lint);
}
/// Determine the eagerness of the given function call.
-fn fn_eagerness<'tcx>(
- cx: &LateContext<'tcx>,
- fn_id: DefId,
- name: Symbol,
- args: &'tcx [Expr<'_>],
-) -> EagernessSuggestion {
+fn fn_eagerness<'tcx>(cx: &LateContext<'tcx>, fn_id: DefId, name: Symbol, have_one_arg: bool) -> EagernessSuggestion {
use EagernessSuggestion::{Eager, Lazy, NoChange};
let name = name.as_str();
None => return Lazy,
};
- if (name.starts_with("as_") || name == "len" || name == "is_empty") && args.len() == 1 {
+ if (name.starts_with("as_") || name == "len" || name == "is_empty") && have_one_arg {
if matches!(
cx.tcx.crate_name(fn_id.krate),
sym::std | sym::core | sym::alloc | sym::proc_macro
},
Res::Def(_, id) => match path {
QPath::Resolved(_, p) => {
- self.eagerness |= fn_eagerness(self.cx, id, p.segments.last().unwrap().ident.name, args);
+ self.eagerness |=
+ fn_eagerness(self.cx, id, p.segments.last().unwrap().ident.name, !args.is_empty());
},
QPath::TypeRelative(_, name) => {
- self.eagerness |= fn_eagerness(self.cx, id, name.ident.name, args);
+ self.eagerness |= fn_eagerness(self.cx, id, name.ident.name, !args.is_empty());
},
QPath::LangItem(..) => self.eagerness = Lazy,
},
self.eagerness |= NoChange;
return;
},
- ExprKind::MethodCall(name, args, _) => {
+ ExprKind::MethodCall(name, ..) => {
self.eagerness |= self
.cx
.typeck_results()
.type_dependent_def_id(e.hir_id)
- .map_or(Lazy, |id| fn_eagerness(self.cx, id, name.ident.name, args));
+ .map_or(Lazy, |id| fn_eagerness(self.cx, id, name.ident.name, true));
},
ExprKind::Index(_, e) => {
let ty = self.cx.typeck_results().expr_ty_adjusted(e);
&& self.eq_expr(l.body, r.body)
})
},
- (&ExprKind::MethodCall(l_path, l_args, _), &ExprKind::MethodCall(r_path, r_args, _)) => {
- self.inner.allow_side_effects && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args)
+ (
+ &ExprKind::MethodCall(l_path, l_receiver, l_args, _),
+ &ExprKind::MethodCall(r_path, r_receiver, r_args, _),
+ ) => {
+ self.inner.allow_side_effects
+ && self.eq_path_segment(l_path, r_path)
+ && self.eq_expr(l_receiver, r_receiver)
+ && self.eq_exprs(l_args, r_args)
},
(&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
self.eq_expr(le, re) && self.eq_array_length(ll, rl)
s.hash(&mut self.s);
},
- ExprKind::MethodCall(path, args, ref _fn_span) => {
+ ExprKind::MethodCall(path, receiver, args, ref _fn_span) => {
self.hash_name(path.ident.name);
+ self.hash_expr(receiver);
self.hash_exprs(args);
},
ExprKind::ConstBlock(ref l_id) => {
.map_or(&[][..], |a| a.args)
.iter()
.filter_map(|a| match a {
- hir::GenericArg::Type(ty) => Some(ty),
+ hir::GenericArg::Type(ty) => Some(*ty),
_ => None,
})
}
pub fn method_calls<'tcx>(
expr: &'tcx Expr<'tcx>,
max_depth: usize,
-) -> (Vec<Symbol>, Vec<&'tcx [Expr<'tcx>]>, Vec<Span>) {
+) -> (Vec<Symbol>, Vec<(&'tcx Expr<'tcx>, &'tcx [Expr<'tcx>])>, Vec<Span>) {
let mut method_names = Vec::with_capacity(max_depth);
let mut arg_lists = Vec::with_capacity(max_depth);
let mut spans = Vec::with_capacity(max_depth);
let mut current = expr;
for _ in 0..max_depth {
- if let ExprKind::MethodCall(path, args, _) = ¤t.kind {
- if args.iter().any(|e| e.span.from_expansion()) {
+ if let ExprKind::MethodCall(path, receiver, args, _) = ¤t.kind {
+ if receiver.span.from_expansion() || args.iter().any(|e| e.span.from_expansion()) {
break;
}
method_names.push(path.ident.name);
- arg_lists.push(&**args);
+ arg_lists.push((*receiver, &**args));
spans.push(path.ident.span);
- current = &args[0];
+ current = receiver;
} else {
break;
}
/// `method_chain_args(expr, &["bar", "baz"])` will return a `Vec`
/// containing the `Expr`s for
/// `.bar()` and `.baz()`
-pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec<&'a [Expr<'a>]>> {
+pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec<(&'a Expr<'a>, &'a [Expr<'a>])>> {
let mut current = expr;
let mut matched = Vec::with_capacity(methods.len());
for method_name in methods.iter().rev() {
// method chains are stored last -> first
- if let ExprKind::MethodCall(path, args, _) = current.kind {
+ if let ExprKind::MethodCall(path, receiver, args, _) = current.kind {
if path.ident.name.as_str() == *method_name {
- if args.iter().any(|e| e.span.from_expansion()) {
+ if receiver.span.from_expansion() || args.iter().any(|e| e.span.from_expansion()) {
return None;
}
- matched.push(args); // build up `matched` backwards
- current = &args[0]; // go to parent expression
+ matched.push((receiver, args)); // build up `matched` backwards
+ current = receiver; // go to parent expression
} else {
return None;
}
ty_is_fn_once_param(cx.tcx, ty.skip_binder(), predicates).then_some(())
})
},
- ExprKind::MethodCall(_, args, _) => {
- let i = args.iter().position(|arg| arg.hir_id == id)?;
+ ExprKind::MethodCall(_, receiver, args, _) => {
+ let i = std::iter::once(receiver)
+ .chain(args.iter())
+ .position(|arg| arg.hir_id == id)?;
let id = cx.typeck_results().type_dependent_def_id(e.hir_id)?;
let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i];
ty_is_fn_once_param(cx.tcx, ty, cx.tcx.param_env(id).caller_bounds()).then_some(())
}
};
- let mut expr = &func.value;
+ let mut expr = func.value;
loop {
match expr.kind {
#[rustfmt::skip]
if abort {
return false;
}
- if let ExprKind::MethodCall(seg, [recv], _) = expr.kind {
+ if let ExprKind::MethodCall(seg, recv, [], _) = expr.kind {
if path_to_local_id(recv, id) {
if seg.ident.name.as_str() == "capacity" {
abort = true;
| AssocOp::LessEqual
| AssocOp::NotEqual
| AssocOp::Greater
- | AssocOp::GreaterEqual => format!(
- "{} {} {}",
- lhs,
- op.to_ast_binop().expect("Those are AST ops").to_string(),
- rhs
- ),
+ | AssocOp::GreaterEqual => {
+ format!(
+ "{} {} {}",
+ lhs,
+ op.to_ast_binop().expect("Those are AST ops").to_string(),
+ rhs
+ )
+ },
AssocOp::Assign => format!("{} = {}", lhs, rhs),
AssocOp::AssignOp(op) => {
format!("{} {}= {}", lhs, token_kind_to_string(&token::BinOp(op)), rhs)
/// indicates whether the function from `parent_expr` takes its args by double reference
fn func_takes_arg_by_double_ref(&self, parent_expr: &'tcx hir::Expr<'_>, cmt_hir_id: HirId) -> bool {
let ty = match parent_expr.kind {
- ExprKind::MethodCall(_, call_args, _) => {
+ ExprKind::MethodCall(_, receiver, call_args, _) => {
if let Some(sig) = self
.cx
.typeck_results()
.type_dependent_def_id(parent_expr.hir_id)
.map(|did| self.cx.tcx.fn_sig(did).skip_binder())
{
- call_args
- .iter()
+ std::iter::once(receiver)
+ .chain(call_args.iter())
.position(|arg| arg.hir_id == cmt_hir_id)
.map(|i| sig.inputs()[i])
} else {
match &parent_expr.kind {
// given expression is the self argument and will be handled completely by the compiler
// i.e.: `|x| x.is_something()`
- ExprKind::MethodCall(_, [self_expr, ..], _) if self_expr.hir_id == cmt.hir_id => {
+ ExprKind::MethodCall(_, self_expr, ..) if self_expr.hir_id == cmt.hir_id => {
let _ = write!(self.suggestion_start, "{}{}", start_snip, ident_str_with_proj);
self.next_pos = span.hi();
return;
},
// item is used in a call
// i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)`
- ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, [_, call_args @ ..], _) => {
+ ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, _, [call_args @ ..], _) => {
let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id);
let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind();
helper(typeck, true, arg, f)?;
}
},
- ExprKind::MethodCall(_, args, _) | ExprKind::Tup(args) | ExprKind::Array(args) => {
+ ExprKind::MethodCall(_, receiver, args, _) => {
+ helper(typeck, true, receiver, f)?;
+ for arg in args {
+ helper(typeck, true, arg, f)?;
+ }
+ },
+ ExprKind::Tup(args) | ExprKind::Array(args) => {
for arg in args {
helper(typeck, true, arg, f)?;
}
}
}
if_chain! {
- if let ExprKind::MethodCall(method_name, args, _) = expr.kind;
+ if let ExprKind::MethodCall(method_name, receiver, args, _) = expr.kind;
if method_name.ident.as_str() == "test";
- if args.len() == 1;
- if let ExprKind::Path(ref qpath) = args[0].kind;
+ if let ExprKind::Path(ref qpath) = receiver.kind;
if match_qpath(qpath, &["test_method_call"]);
+ if args.is_empty();
then {
// report your lint here
}
//! make gcc/clang pass `-flavor <flavor>` as the first two arguments in the linker invocation
//! and since Windows does not support symbolic links for files this wrapper is used in place of a
//! symbolic link. It execs `../rust-lld -flavor <flavor>` by propagating the flavor argument
-//! passed to the wrapper as the first two arguments. On Windows it spawns a `..\rust-lld.exe`
-//! child process.
+//! obtained from the wrapper's name as the first two arguments.
+//! On Windows it spawns a `..\rust-lld.exe` child process.
use std::fmt::Display;
use std::path::{Path, PathBuf};
rust_lld_path
}
+/// Extract LLD flavor name from the lld-wrapper executable name.
+fn get_lld_flavor(current_exe_path: &Path) -> Result<&'static str, String> {
+ let stem = current_exe_path.file_stem();
+ Ok(match stem.and_then(|s| s.to_str()) {
+ Some("ld.lld") => "gnu",
+ Some("ld64.lld") => "darwin",
+ Some("lld-link") => "link",
+ Some("wasm-ld") => "wasm",
+ _ => return Err(format!("{:?}", stem)),
+ })
+}
+
/// Returns the command for invoking rust-lld with the correct flavor.
-/// LLD only accepts the flavor argument at the first two arguments, so move it there.
+/// LLD only accepts the flavor argument at the first two arguments, so pass it there.
///
/// Exits on error.
fn get_rust_lld_command(current_exe_path: &Path) -> process::Command {
let rust_lld_path = get_rust_lld_path(current_exe_path);
let mut command = process::Command::new(rust_lld_path);
- let mut flavor = None;
- let args = env::args_os()
- .skip(1)
- .filter(|arg| match arg.to_str().and_then(|s| s.strip_prefix("-rustc-lld-flavor=")) {
- Some(suffix) => {
- flavor = Some(suffix.to_string());
- false
- }
- None => true,
- })
- .collect::<Vec<_>>();
+ let flavor =
+ get_lld_flavor(current_exe_path).unwrap_or_exit_with("executable has unexpected name");
command.arg("-flavor");
- command.arg(flavor.unwrap_or_exit_with("-rustc-lld-flavor=<flavor> is not passed"));
- command.args(args);
+ command.arg(flavor);
+ command.args(env::args_os().skip(1));
command
}
-Subproject commit 8c8b479be723fb103b0b1203faf9246a3f587250
+Subproject commit dba35d2be72f4b78343d1a0f0b4737306f310672
walk::filter_dirs(path)
// We exempt these as they require the placeholder
// for their operation
- || path.ends_with("compiler/rustc_passes/src/lib_features.rs")
+ || path.ends_with("compiler/rustc_attr/src/builtin.rs")
|| path.ends_with("src/tools/tidy/src/features/version.rs")
|| path.ends_with("src/tools/replace-version-placeholder")
},
curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true }
# Ensure default features of libz-sys, which are disabled in some scenarios.
libz-sys = { version = "1.1.2" }
-# The only user of memchr's deprecated `use_std` feature is `combine`, so this can be
-# removed if/when https://github.com/Marwes/combine/pull/348 is merged and released.
-memchr = { version = "2.5", features = ["std", "use_std"] }
# Ensure default features of regex, which are disabled in some scenarios.
regex = { version = "1.5.6" }
serde_json = { version = "1.0.31", features = ["raw_value", "unbounded_depth"] }
"autocfg",
"bitflags",
"block-buffer",
- "block-padding",
- "byte-tools",
- "byteorder",
"cc",
"cfg-if",
"chalk-derive",
"ena",
"env_logger",
"expect-test",
- "fake-simd",
"fallible-iterator", // dependency of `thorin`
"filetime",
"fixedbitset",
"object",
"odht",
"once_cell",
- "opaque-debug",
"parking_lot",
"parking_lot_core",
"pathdiff",
+#[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
#[inline(always)]
-fn bitset_search<
+const fn bitset_search<
const N: usize,
const CHUNK_SIZE: usize,
const N1: usize,
let bucket_idx = (needle / 64) as usize;
let chunk_map_idx = bucket_idx / CHUNK_SIZE;
let chunk_piece = bucket_idx % CHUNK_SIZE;
- let chunk_idx = if let Some(&v) = chunk_idx_map.get(chunk_map_idx) {
- v
+ // FIXME: const-hack: Revert to `slice::get` after `const_slice_index`
+ // feature stabilizes.
+ let chunk_idx = if chunk_map_idx < chunk_idx_map.len() {
+ chunk_idx_map[chunk_map_idx]
} else {
return false;
};
let idx = bitset_chunk_idx[chunk_idx as usize][chunk_piece] as usize;
- let word = if let Some(word) = bitset_canonical.get(idx) {
- *word
+ // FIXME: const-hack: Revert to `slice::get` after `const_slice_index`
+ // feature stabilizes.
+ let word = if idx < bitset_canonical.len() {
+ bitset_canonical[idx]
} else {
let (real_idx, mapping) = bitset_canonicalized[idx - bitset_canonical.len()];
let mut word = bitset_canonical[real_idx as usize];
writeln!(
&mut self.file,
- "static BITSET_CANONICAL: [u64; {}] = [{}];",
+ "const BITSET_CANONICAL: &'static [u64; {}] = &[{}];",
canonicalized.canonical_words.len(),
fmt_list(canonicalized.canonical_words.iter().map(|v| Bits(*v))),
)
self.bytes_used += 8 * canonicalized.canonical_words.len();
writeln!(
&mut self.file,
- "static BITSET_MAPPING: [(u8, u8); {}] = [{}];",
+ "const BITSET_MAPPING: &'static [(u8, u8); {}] = &[{}];",
canonicalized.canonicalized_words.len(),
fmt_list(&canonicalized.canonicalized_words),
)
self.blank_line();
- writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap();
+ writeln!(
+ &mut self.file,
+ r#"#[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]"#
+ )
+ .unwrap();
+ writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap();
writeln!(&mut self.file, " super::bitset_search(",).unwrap();
writeln!(&mut self.file, " c as u32,").unwrap();
writeln!(&mut self.file, " &BITSET_CHUNKS_MAP,").unwrap();
writeln!(
&mut self.file,
- "static BITSET_CHUNKS_MAP: [u8; {}] = [{}];",
+ "const BITSET_CHUNKS_MAP: &'static [u8; {}] = &[{}];",
chunk_indices.len(),
fmt_list(&chunk_indices),
)
self.bytes_used += chunk_indices.len();
writeln!(
&mut self.file,
- "static BITSET_INDEX_CHUNKS: [[u8; {}]; {}] = [{}];",
+ "const BITSET_INDEX_CHUNKS: &'static [[u8; {}]; {}] = &[{}];",
chunk_length,
chunks.len(),
fmt_list(chunks.iter()),
* Changing observable runtime behavior of library APIs
"""
-[mentions."library/proc_macro/src/bridge"]
-cc = ["@rust-lang/wg-rls-2"]
-
[mentions."src/librustdoc/clean/types.rs"]
cc = ["@camelid"]