mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Auto merge of #154092 - JonathanBrouwer:rollup-GKNFJe0, r=JonathanBrouwer
Rollup of 19 pull requests Successful merges: - rust-lang/rust#152870 (Do not enable split debuginfo for windows-gnu) - rust-lang/rust#153333 (Fix bootstrap rust build failure for vxworks) - rust-lang/rust#153681 (ci: add runners for vanilla LLVM 22) - rust-lang/rust#153727 (When single impl can satisfy inference error, suggest type) - rust-lang/rust#153824 (Add `Wake` diagnostic item for `alloc::task::Wake`) - rust-lang/rust#154077 (Optimize 128-bit integer formatting) - rust-lang/rust#154078 (`define_callbacks` tweaks) - rust-lang/rust#151905 (Split the `dec2flt::RawFloat` trait for easier reuse) - rust-lang/rust#153170 (Add is_disconnected functions to mpsc and mpmc channels) - rust-lang/rust#153308 (Add hygiene annotations for tokens in `macro_rules!` bodies) - rust-lang/rust#153557 (fix inference variables leaking into HIR const literal lowering logic) - rust-lang/rust#153804 (Derive Macro Eq: link to more detailed documentation) - rust-lang/rust#153913 (Fix some suggestions of the `for-loops-over-fallibles` lint) - rust-lang/rust#153974 (Point at return type when it is the source of the type expectation) - rust-lang/rust#153987 (mGCA: Lower const generic args to infer when needed) - rust-lang/rust#154018 (simplify and remove `tests/ui/kindck` and related tests) - rust-lang/rust#154036 (borrowck/type_check: remove helper left-over from unsized locals) - rust-lang/rust#154038 (merge `regions-outlives-nominal-type-*` tests into one file) - rust-lang/rust#154041 (bootstrap: Allow `--bless`ing changes to editor settings files)
This commit is contained in:
@@ -1013,9 +1013,10 @@
|
||||
# its historical default, but when compiling the compiler itself, we skip it by
|
||||
# default since we know it's safe to do so in that case.
|
||||
#
|
||||
# On Windows platforms, packed debuginfo is the only supported option,
|
||||
# producing a `.pdb` file.
|
||||
#split-debuginfo = if linux { off } else if windows { packed } else if apple { unpacked }
|
||||
# On Windows MSVC platforms, packed debuginfo is the only supported option,
|
||||
# producing a `.pdb` file. On Windows GNU rustc doesn't support splitting debuginfo,
|
||||
# and enabling it causes issues.
|
||||
#split-debuginfo = if linux || windows-gnu { off } else if windows-msvc { packed } else if apple { unpacked }
|
||||
|
||||
# Path to the `llvm-config` binary of the installation of a custom LLVM to link
|
||||
# against. Note that if this is specified we don't compile LLVM at all for this
|
||||
|
||||
@@ -1310,9 +1310,13 @@ fn lower_generic_arg(
|
||||
}
|
||||
GenericArg::Type(self.lower_ty_alloc(ty, itctx).try_as_ambig_ty().unwrap())
|
||||
}
|
||||
ast::GenericArg::Const(ct) => GenericArg::Const(
|
||||
self.lower_anon_const_to_const_arg_and_alloc(ct).try_as_ambig_ct().unwrap(),
|
||||
),
|
||||
ast::GenericArg::Const(ct) => {
|
||||
let ct = self.lower_anon_const_to_const_arg_and_alloc(ct);
|
||||
match ct.try_as_ambig_ct() {
|
||||
Some(ct) => GenericArg::Const(ct),
|
||||
None => GenericArg::Infer(hir::InferArg { hir_id: ct.hir_id, span: ct.span }),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -737,6 +737,23 @@ fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) -> Spacing {
|
||||
TokenTree::Token(token, spacing) => {
|
||||
let token_str = self.token_to_string_ext(token, convert_dollar_crate);
|
||||
self.word(token_str);
|
||||
// Emit hygiene annotations for identity-bearing tokens,
|
||||
// matching how print_ident() and print_lifetime() call ann_post().
|
||||
match token.kind {
|
||||
token::Ident(name, _) => {
|
||||
self.ann_post(Ident::new(name, token.span));
|
||||
}
|
||||
token::NtIdent(ident, _) => {
|
||||
self.ann_post(ident);
|
||||
}
|
||||
token::Lifetime(name, _) => {
|
||||
self.ann_post(Ident::new(name, token.span));
|
||||
}
|
||||
token::NtLifetime(ident, _) => {
|
||||
self.ann_post(ident);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if let token::DocComment(..) = token.kind {
|
||||
self.hardbreak()
|
||||
}
|
||||
|
||||
@@ -374,10 +374,6 @@ fn body(&self) -> &Body<'tcx> {
|
||||
self.body
|
||||
}
|
||||
|
||||
fn unsized_feature_enabled(&self) -> bool {
|
||||
self.tcx().features().unsized_fn_params()
|
||||
}
|
||||
|
||||
/// Equate the inferred type and the annotated type for user type annotations
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn check_user_type_annotations(&mut self) {
|
||||
@@ -660,7 +656,7 @@ fn visit_statement(&mut self, stmt: &Statement<'tcx>, location: Location) {
|
||||
);
|
||||
}
|
||||
|
||||
if !self.unsized_feature_enabled() {
|
||||
if !self.tcx().features().unsized_fn_params() {
|
||||
let trait_ref = ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(LangItem::Sized, self.last_span),
|
||||
@@ -936,9 +932,10 @@ fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
|
||||
}
|
||||
}
|
||||
|
||||
// When `unsized_fn_params` is enabled, only function calls
|
||||
// and nullary ops are checked in `check_call_dest`.
|
||||
if !self.unsized_feature_enabled() {
|
||||
// When `unsized_fn_params` is enabled, this is checked in `check_call_dest`,
|
||||
// and `hir_typeck` still forces all non-argument locals to be sized (i.e., we don't
|
||||
// fully re-check what was already checked on HIR).
|
||||
if !self.tcx().features().unsized_fn_params() {
|
||||
match self.body.local_kind(local) {
|
||||
LocalKind::ReturnPointer | LocalKind::Arg => {
|
||||
// return values of normal functions are required to be
|
||||
@@ -1953,8 +1950,8 @@ fn check_call_dest(
|
||||
}
|
||||
|
||||
// When `unsized_fn_params` is not enabled,
|
||||
// this check is done at `check_local`.
|
||||
if self.unsized_feature_enabled() {
|
||||
// this check is done at `visit_local_decl`.
|
||||
if self.tcx().features().unsized_fn_params() {
|
||||
let span = term.source_info.span;
|
||||
self.ensure_place_sized(dest_ty, span);
|
||||
}
|
||||
|
||||
@@ -2874,6 +2874,9 @@ fn lower_const_arg_literal(
|
||||
span: Span,
|
||||
) -> Const<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let ty = if !ty.has_infer() { Some(ty) } else { None };
|
||||
|
||||
if let LitKind::Err(guar) = *kind {
|
||||
return ty::Const::new_error(tcx, guar);
|
||||
}
|
||||
@@ -2905,16 +2908,20 @@ fn try_lower_anon_const_lit(
|
||||
};
|
||||
|
||||
let lit_input = match expr.kind {
|
||||
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: lit.node, ty, neg: false }),
|
||||
hir::ExprKind::Lit(lit) => {
|
||||
Some(LitToConstInput { lit: lit.node, ty: Some(ty), neg: false })
|
||||
}
|
||||
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
|
||||
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: lit.node, ty, neg: true }),
|
||||
hir::ExprKind::Lit(lit) => {
|
||||
Some(LitToConstInput { lit: lit.node, ty: Some(ty), neg: true })
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
lit_input.and_then(|l| {
|
||||
if const_lit_matches_ty(tcx, &l.lit, l.ty, l.neg) {
|
||||
if const_lit_matches_ty(tcx, &l.lit, ty, l.neg) {
|
||||
tcx.at(expr.span)
|
||||
.lit_to_const(l)
|
||||
.map(|value| ty::Const::new_value(tcx, value.valtree, value.ty))
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{Expr, ExprKind, HirId, LangItem, Node, QPath, is_range_literal};
|
||||
use rustc_hir::{Expr, ExprKind, FnRetTy, HirId, LangItem, Node, QPath, is_range_literal};
|
||||
use rustc_hir_analysis::check::potentially_plural_count;
|
||||
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, PermitVariants};
|
||||
use rustc_index::IndexVec;
|
||||
@@ -1582,6 +1582,45 @@ struct MismatchedParam<'a> {
|
||||
}
|
||||
}
|
||||
err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id)));
|
||||
if let DefKind::Fn | DefKind::AssocFn = self.tcx.def_kind(def_id)
|
||||
&& let ty::Param(_) =
|
||||
self.tcx.fn_sig(def_id).instantiate_identity().skip_binder().output().kind()
|
||||
&& let parent = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id
|
||||
&& let Some((output, body_id)) = match self.tcx.hir_node_by_def_id(parent) {
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Fn { sig, body, .. },
|
||||
..
|
||||
})
|
||||
| hir::Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body)),
|
||||
..
|
||||
})
|
||||
| hir::Node::ImplItem(hir::ImplItem {
|
||||
kind: hir::ImplItemKind::Fn(sig, body),
|
||||
..
|
||||
}) => Some((sig.decl.output, body)),
|
||||
_ => None,
|
||||
}
|
||||
&& let expr = self.tcx.hir_body(*body_id).value
|
||||
&& (expr.peel_blocks().span == call_expr.span
|
||||
|| matches!(
|
||||
self.tcx.parent_hir_node(call_expr.hir_id),
|
||||
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. })
|
||||
))
|
||||
{
|
||||
err.span_label(
|
||||
output.span(),
|
||||
match output {
|
||||
FnRetTy::DefaultReturn(_) => format!(
|
||||
"this implicit `()` return type influences the call expression's return type"
|
||||
),
|
||||
FnRetTy::Return(_) => {
|
||||
"this return type influences the call expression's return type"
|
||||
.to_string()
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
} else if let Some(hir::Node::Expr(e)) = self.tcx.hir_get_if_local(def_id)
|
||||
&& let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
|
||||
{
|
||||
|
||||
@@ -49,6 +49,11 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
let Some((pat, arg)) = extract_for_loop(expr) else { return };
|
||||
|
||||
// Do not put suggestions for external macros.
|
||||
if pat.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
||||
let arg_span = arg.span.source_callsite();
|
||||
|
||||
let ty = cx.typeck_results().expr_ty(arg);
|
||||
@@ -77,6 +82,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
};
|
||||
|
||||
let sub = if let Some(recv) = extract_iterator_next_call(cx, arg)
|
||||
&& recv.span.can_be_used_for_suggestions()
|
||||
&& recv.span.between(arg_span.shrink_to_hi()).can_be_used_for_suggestions()
|
||||
&& let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span)
|
||||
{
|
||||
ForLoopsOverFalliblesLoopSub::RemoveNext {
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono,
|
||||
};
|
||||
use crate::query::describe_as_module;
|
||||
use crate::query::plumbing::{define_callbacks, query_helper_param_ty};
|
||||
use crate::query::plumbing::{define_callbacks, maybe_into_query_key};
|
||||
use crate::traits::query::{
|
||||
CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal,
|
||||
CanonicalMethodAutoderefStepsGoal, CanonicalPredicateGoal, CanonicalTypeOpAscribeUserTypeGoal,
|
||||
|
||||
@@ -201,6 +201,13 @@ pub struct TyCtxtEnsureDone<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
/// Returns a transparent wrapper for `TyCtxt` which uses
|
||||
/// `span` as the location of queries performed through it.
|
||||
#[inline(always)]
|
||||
pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
|
||||
TyCtxtAt { tcx: self, span }
|
||||
}
|
||||
|
||||
/// FIXME: `ensure_ok`'s effects are subtle. Is this comment fully accurate?
|
||||
///
|
||||
/// Wrapper that calls queries in a special "ensure OK" mode, for callers
|
||||
@@ -258,16 +265,9 @@ pub fn ensure_result(self) -> TyCtxtEnsureResult<'tcx> {
|
||||
pub fn ensure_done(self) -> TyCtxtEnsureDone<'tcx> {
|
||||
TyCtxtEnsureDone { tcx: self }
|
||||
}
|
||||
|
||||
/// Returns a transparent wrapper for `TyCtxt` which uses
|
||||
/// `span` as the location of queries performed through it.
|
||||
#[inline(always)]
|
||||
pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
|
||||
TyCtxtAt { tcx: self, span }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! query_helper_param_ty {
|
||||
macro_rules! maybe_into_query_key {
|
||||
(DefId) => { impl $crate::query::IntoQueryKey<DefId> };
|
||||
(LocalDefId) => { impl $crate::query::IntoQueryKey<LocalDefId> };
|
||||
($K:ty) => { $K };
|
||||
@@ -276,7 +276,7 @@ macro_rules! query_helper_param_ty {
|
||||
macro_rules! define_callbacks {
|
||||
(
|
||||
// You might expect the key to be `$K:ty`, but it needs to be `$($K:tt)*` so that
|
||||
// `query_helper_param_ty!` can match on specific type names.
|
||||
// `maybe_into_query_key!` can match on specific type names.
|
||||
queries {
|
||||
$(
|
||||
$(#[$attr:meta])*
|
||||
@@ -323,6 +323,9 @@ pub mod $name {
|
||||
#[cfg(not($arena_cache))]
|
||||
pub type ProvidedValue<'tcx> = Value<'tcx>;
|
||||
|
||||
pub type Cache<'tcx> =
|
||||
<Key<'tcx> as $crate::query::QueryKey>::Cache<Erased<Value<'tcx>>>;
|
||||
|
||||
/// This helper function takes a value returned by the query provider
|
||||
/// (or loaded from disk, or supplied by query feeding), allocates
|
||||
/// it in an arena if requested by the `arena_cache` modifier, and
|
||||
@@ -354,9 +357,6 @@ pub fn provided_to_erased<'tcx>(
|
||||
erase::erase_val(value)
|
||||
}
|
||||
|
||||
pub type Cache<'tcx> =
|
||||
<Key<'tcx> as $crate::query::QueryKey>::Cache<Erased<Value<'tcx>>>;
|
||||
|
||||
// Ensure that keys grow no larger than 88 bytes by accident.
|
||||
// Increase this limit if necessary, but do try to keep the size low if possible
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
@@ -390,116 +390,8 @@ pub fn provided_to_erased<'tcx>(
|
||||
}
|
||||
)*
|
||||
|
||||
/// Holds per-query arenas for queries with the `arena_cache` modifier.
|
||||
#[derive(Default)]
|
||||
pub struct QueryArenas<'tcx> {
|
||||
$(
|
||||
// Use the `ArenaCached` helper trait to determine the arena's value type.
|
||||
#[cfg($arena_cache)]
|
||||
pub $name: TypedArena<
|
||||
<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated,
|
||||
>,
|
||||
)*
|
||||
}
|
||||
|
||||
impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> {
|
||||
$(
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
|
||||
crate::query::inner::query_ensure_ok_or_done(
|
||||
self.tcx,
|
||||
&self.tcx.query_system.query_vtables.$name,
|
||||
$crate::query::IntoQueryKey::into_query_key(key),
|
||||
$crate::query::EnsureMode::Ok,
|
||||
)
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
// Only defined when the `ensure_result` modifier is present.
|
||||
impl<'tcx> $crate::query::TyCtxtEnsureResult<'tcx> {
|
||||
$(
|
||||
#[cfg($returns_error_guaranteed)]
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(
|
||||
self,
|
||||
key: query_helper_param_ty!($($K)*),
|
||||
) -> Result<(), rustc_errors::ErrorGuaranteed> {
|
||||
crate::query::inner::query_ensure_result(
|
||||
self.tcx,
|
||||
&self.tcx.query_system.query_vtables.$name,
|
||||
$crate::query::IntoQueryKey::into_query_key(key),
|
||||
)
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> {
|
||||
$(
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
|
||||
crate::query::inner::query_ensure_ok_or_done(
|
||||
self.tcx,
|
||||
&self.tcx.query_system.query_vtables.$name,
|
||||
$crate::query::IntoQueryKey::into_query_key(key),
|
||||
$crate::query::EnsureMode::Done,
|
||||
);
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
$(
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
|
||||
self.at(DUMMY_SP).$name(key)
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
impl<'tcx> $crate::query::TyCtxtAt<'tcx> {
|
||||
$(
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
|
||||
use $crate::query::{erase, inner};
|
||||
|
||||
erase::restore_val::<$V>(inner::query_get_at(
|
||||
self.tcx,
|
||||
self.span,
|
||||
&self.tcx.query_system.query_vtables.$name,
|
||||
$crate::query::IntoQueryKey::into_query_key(key),
|
||||
))
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
$(
|
||||
#[cfg($feedable)]
|
||||
impl<'tcx, K: $crate::query::IntoQueryKey<$name::Key<'tcx>> + Copy>
|
||||
TyCtxtFeed<'tcx, K>
|
||||
{
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
|
||||
let key = self.key().into_query_key();
|
||||
let erased_value = $name::provided_to_erased(self.tcx, value);
|
||||
$crate::query::inner::query_feed(
|
||||
self.tcx,
|
||||
&self.tcx.query_system.query_vtables.$name,
|
||||
key,
|
||||
erased_value,
|
||||
);
|
||||
}
|
||||
}
|
||||
)*
|
||||
|
||||
/// Identifies a query by kind and key. This is in contrast to `QueryJobId` which is just a number.
|
||||
/// Identifies a query by kind and key. This is in contrast to `QueryJobId` which is just a
|
||||
/// number.
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TaggedQueryKey<'tcx> {
|
||||
@@ -528,7 +420,8 @@ pub fn query_name(&self) -> &'static str {
|
||||
pub fn description(&self, tcx: TyCtxt<'tcx>) -> String {
|
||||
let (name, description) = ty::print::with_no_queries!(match self {
|
||||
$(
|
||||
TaggedQueryKey::$name(key) => (stringify!($name), _description_fns::$name(tcx, *key)),
|
||||
TaggedQueryKey::$name(key) =>
|
||||
(stringify!($name), _description_fns::$name(tcx, *key)),
|
||||
)*
|
||||
});
|
||||
if tcx.sess.verbose_internals() {
|
||||
@@ -550,7 +443,8 @@ pub fn default_span(&self, tcx: TyCtxt<'tcx>, span: Span) -> Span {
|
||||
}
|
||||
match self {
|
||||
$(
|
||||
TaggedQueryKey::$name(key) => crate::query::QueryKey::default_span(key, tcx),
|
||||
TaggedQueryKey::$name(key) =>
|
||||
$crate::query::QueryKey::default_span(key, tcx),
|
||||
)*
|
||||
}
|
||||
}
|
||||
@@ -558,14 +452,20 @@ pub fn default_span(&self, tcx: TyCtxt<'tcx>, span: Span) -> Span {
|
||||
pub fn def_kind(&self, tcx: TyCtxt<'tcx>) -> Option<DefKind> {
|
||||
// This is used to reduce code generation as it
|
||||
// can be reused for queries with the same key type.
|
||||
fn inner<'tcx>(key: &impl crate::query::QueryKey, tcx: TyCtxt<'tcx>) -> Option<DefKind> {
|
||||
key.key_as_def_id().and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id))
|
||||
fn inner<'tcx>(key: &impl $crate::query::QueryKey, tcx: TyCtxt<'tcx>)
|
||||
-> Option<DefKind>
|
||||
{
|
||||
key
|
||||
.key_as_def_id()
|
||||
.and_then(|def_id| def_id.as_local())
|
||||
.map(|def_id| tcx.def_kind(def_id))
|
||||
}
|
||||
|
||||
if let TaggedQueryKey::def_kind(..) = self {
|
||||
// Try to avoid infinite recursion.
|
||||
return None
|
||||
}
|
||||
|
||||
match self {
|
||||
$(
|
||||
TaggedQueryKey::$name(key) => inner(key, tcx),
|
||||
@@ -577,7 +477,19 @@ fn inner<'tcx>(key: &impl crate::query::QueryKey, tcx: TyCtxt<'tcx>) -> Option<D
|
||||
/// Holds a `QueryVTable` for each query.
|
||||
pub struct QueryVTables<'tcx> {
|
||||
$(
|
||||
pub $name: crate::query::QueryVTable<'tcx, $name::Cache<'tcx>>,
|
||||
pub $name: $crate::query::QueryVTable<'tcx, $name::Cache<'tcx>>,
|
||||
)*
|
||||
}
|
||||
|
||||
/// Holds per-query arenas for queries with the `arena_cache` modifier.
|
||||
#[derive(Default)]
|
||||
pub struct QueryArenas<'tcx> {
|
||||
$(
|
||||
// Use the `ArenaCached` helper trait to determine the arena's value type.
|
||||
#[cfg($arena_cache)]
|
||||
pub $name: TypedArena<
|
||||
<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated,
|
||||
>,
|
||||
)*
|
||||
}
|
||||
|
||||
@@ -637,12 +549,108 @@ impl Copy for ExternProviders {}
|
||||
impl Clone for ExternProviders {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
$(
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn $name(self, key: maybe_into_query_key!($($K)*)) -> $V {
|
||||
self.at(DUMMY_SP).$name(key)
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
impl<'tcx> $crate::query::TyCtxtAt<'tcx> {
|
||||
$(
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(self, key: maybe_into_query_key!($($K)*)) -> $V {
|
||||
use $crate::query::{erase, inner};
|
||||
|
||||
erase::restore_val::<$V>(inner::query_get_at(
|
||||
self.tcx,
|
||||
self.span,
|
||||
&self.tcx.query_system.query_vtables.$name,
|
||||
$crate::query::IntoQueryKey::into_query_key(key),
|
||||
))
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> {
|
||||
$(
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(self, key: maybe_into_query_key!($($K)*)) {
|
||||
$crate::query::inner::query_ensure_ok_or_done(
|
||||
self.tcx,
|
||||
&self.tcx.query_system.query_vtables.$name,
|
||||
$crate::query::IntoQueryKey::into_query_key(key),
|
||||
$crate::query::EnsureMode::Ok,
|
||||
)
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
// Only defined when the `returns_error_guaranteed` modifier is present.
|
||||
impl<'tcx> $crate::query::TyCtxtEnsureResult<'tcx> {
|
||||
$(
|
||||
#[cfg($returns_error_guaranteed)]
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(
|
||||
self,
|
||||
key: maybe_into_query_key!($($K)*),
|
||||
) -> Result<(), rustc_errors::ErrorGuaranteed> {
|
||||
$crate::query::inner::query_ensure_result(
|
||||
self.tcx,
|
||||
&self.tcx.query_system.query_vtables.$name,
|
||||
$crate::query::IntoQueryKey::into_query_key(key),
|
||||
)
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> {
|
||||
$(
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(self, key: maybe_into_query_key!($($K)*)) {
|
||||
$crate::query::inner::query_ensure_ok_or_done(
|
||||
self.tcx,
|
||||
&self.tcx.query_system.query_vtables.$name,
|
||||
$crate::query::IntoQueryKey::into_query_key(key),
|
||||
$crate::query::EnsureMode::Done,
|
||||
);
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
$(
|
||||
// Only defined when the `feedable` modifier is present.
|
||||
#[cfg($feedable)]
|
||||
impl<'tcx, K: $crate::query::IntoQueryKey<$name::Key<'tcx>> + Copy>
|
||||
TyCtxtFeed<'tcx, K>
|
||||
{
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
|
||||
$crate::query::inner::query_feed(
|
||||
self.tcx,
|
||||
&self.tcx.query_system.query_vtables.$name,
|
||||
self.key().into_query_key(),
|
||||
$name::provided_to_erased(self.tcx, value),
|
||||
);
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
// Re-export `macro_rules!` macros as normal items, so that they can be imported normally.
|
||||
pub(crate) use define_callbacks;
|
||||
pub(crate) use query_helper_param_ty;
|
||||
pub(crate) use maybe_into_query_key;
|
||||
|
||||
#[cold]
|
||||
pub(crate) fn default_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
|
||||
|
||||
@@ -10,7 +10,10 @@ pub struct LitToConstInput<'tcx> {
|
||||
/// The absolute value of the resultant constant.
|
||||
pub lit: LitKind,
|
||||
/// The type of the constant.
|
||||
pub ty: Ty<'tcx>,
|
||||
///
|
||||
/// `None` is used by const generics when the type of the constant is unknown, e.g.
|
||||
/// if there are inference variables
|
||||
pub ty: Option<Ty<'tcx>>,
|
||||
/// If the constant is negative.
|
||||
pub neg: bool,
|
||||
}
|
||||
|
||||
@@ -50,7 +50,8 @@ pub(crate) fn as_constant_inner<'tcx>(
|
||||
|
||||
match *kind {
|
||||
ExprKind::Literal { lit, neg } => {
|
||||
let const_ = lit_to_mir_constant(tcx, LitToConstInput { lit: lit.node, ty, neg });
|
||||
let const_ =
|
||||
lit_to_mir_constant(tcx, LitToConstInput { lit: lit.node, ty: Some(ty), neg });
|
||||
|
||||
ConstOperand { span, user_ty: None, const_ }
|
||||
}
|
||||
@@ -109,6 +110,8 @@ pub(crate) fn as_constant_inner<'tcx>(
|
||||
fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>) -> Const<'tcx> {
|
||||
let LitToConstInput { lit, ty, neg } = lit_input;
|
||||
|
||||
let ty = ty.expect("type of literal must be known at this point");
|
||||
|
||||
if let Err(guar) = ty.error_reported() {
|
||||
return Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar));
|
||||
}
|
||||
|
||||
@@ -31,25 +31,27 @@ pub(crate) fn lit_to_const<'tcx>(
|
||||
.unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result))
|
||||
};
|
||||
|
||||
let (valtree, valtree_ty) = match (lit, expected_ty.kind()) {
|
||||
let (valtree, valtree_ty) = match (lit, expected_ty.map(|ty| ty.kind())) {
|
||||
(ast::LitKind::Str(s, _), _) => {
|
||||
let str_bytes = s.as_str().as_bytes();
|
||||
let valtree_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_);
|
||||
(ty::ValTree::from_raw_bytes(tcx, str_bytes), valtree_ty)
|
||||
}
|
||||
(ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _))
|
||||
(ast::LitKind::ByteStr(byte_sym, _), Some(ty::Ref(_, inner_ty, _)))
|
||||
if let ty::Slice(ty) | ty::Array(ty, _) = inner_ty.kind()
|
||||
&& let ty::Uint(UintTy::U8) = ty.kind() =>
|
||||
{
|
||||
(ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty)
|
||||
(ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty.unwrap())
|
||||
}
|
||||
(ast::LitKind::ByteStr(byte_sym, _), ty::Slice(inner_ty) | ty::Array(inner_ty, _))
|
||||
if tcx.features().deref_patterns()
|
||||
&& let ty::Uint(UintTy::U8) = inner_ty.kind() =>
|
||||
(
|
||||
ast::LitKind::ByteStr(byte_sym, _),
|
||||
Some(ty::Slice(inner_ty) | ty::Array(inner_ty, _)),
|
||||
) if tcx.features().deref_patterns()
|
||||
&& let ty::Uint(UintTy::U8) = inner_ty.kind() =>
|
||||
{
|
||||
// Byte string literal patterns may have type `[u8]` or `[u8; N]` if `deref_patterns` is
|
||||
// enabled, in order to allow, e.g., `deref!(b"..."): Vec<u8>`.
|
||||
(ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty)
|
||||
(ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty.unwrap())
|
||||
}
|
||||
(ast::LitKind::ByteStr(byte_sym, _), _) => {
|
||||
let valtree = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str());
|
||||
@@ -79,11 +81,11 @@ pub(crate) fn lit_to_const<'tcx>(
|
||||
trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned());
|
||||
(ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, i))
|
||||
}
|
||||
(ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), ty::Uint(ui)) if !neg => {
|
||||
(ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), Some(ty::Uint(ui))) if !neg => {
|
||||
let scalar_int = trunc(n.get(), *ui);
|
||||
(ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, *ui))
|
||||
}
|
||||
(ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), ty::Int(i)) => {
|
||||
(ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), Some(ty::Int(i))) => {
|
||||
// Unsigned "negation" has the same bitwise effect as signed negation,
|
||||
// which gets the result we want without additional casts.
|
||||
let scalar_int =
|
||||
@@ -101,7 +103,7 @@ pub(crate) fn lit_to_const<'tcx>(
|
||||
let bits = parse_float_into_scalar(n, fty, neg)?;
|
||||
(ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, fty))
|
||||
}
|
||||
(ast::LitKind::Float(n, ast::LitFloatType::Unsuffixed), ty::Float(fty)) => {
|
||||
(ast::LitKind::Float(n, ast::LitFloatType::Unsuffixed), Some(ty::Float(fty))) => {
|
||||
let bits = parse_float_into_scalar(n, *fty, neg)?;
|
||||
(ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, *fty))
|
||||
}
|
||||
|
||||
@@ -696,7 +696,7 @@ fn lower_pat_expr(
|
||||
// patterns to `str`, and byte-string literal patterns to `[u8; N]` or `[u8]`.
|
||||
|
||||
let pat_ty = self.typeck_results.node_type(pat.hir_id);
|
||||
let lit_input = LitToConstInput { lit: lit.node, ty: pat_ty, neg: *negated };
|
||||
let lit_input = LitToConstInput { lit: lit.node, ty: Some(pat_ty), neg: *negated };
|
||||
let constant = const_lit_matches_ty(self.tcx, &lit.node, pat_ty, *negated)
|
||||
.then(|| self.tcx.at(expr.span).lit_to_const(lit_input))
|
||||
.flatten()
|
||||
|
||||
@@ -158,6 +158,7 @@ fn try_get_prefix(&self) -> Option<&str> {
|
||||
|
||||
struct ClosureEraser<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
depth: usize,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ClosureEraser<'a, 'tcx> {
|
||||
@@ -172,7 +173,8 @@ fn cx(&self) -> TyCtxt<'tcx> {
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
match ty.kind() {
|
||||
self.depth += 1;
|
||||
let ty = match ty.kind() {
|
||||
ty::Closure(_, args) => {
|
||||
// For a closure type, we turn it into a function pointer so that it gets rendered
|
||||
// as `fn(args) -> Ret`.
|
||||
@@ -233,9 +235,15 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
// its type parameters.
|
||||
ty.super_fold_with(self)
|
||||
}
|
||||
// We don't have an unknown type parameter anywhere, replace with `_`.
|
||||
// We are in the top-level type, not one of its type parameters. Name it with its
|
||||
// parameters replaced.
|
||||
_ if self.depth == 1 => ty.super_fold_with(self),
|
||||
// We don't have an unknown type parameter anywhere, and we are in a type parameter.
|
||||
// Replace with `_`.
|
||||
_ => self.new_infer(),
|
||||
}
|
||||
};
|
||||
self.depth -= 1;
|
||||
ty
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
@@ -287,7 +295,7 @@ fn ty_to_string<'tcx>(
|
||||
let ty = infcx.resolve_vars_if_possible(ty);
|
||||
// We use `fn` ptr syntax for closures, but this only works when the closure does not capture
|
||||
// anything. We also remove all type parameters that are fully known to the type system.
|
||||
let ty = ty.fold_with(&mut ClosureEraser { infcx });
|
||||
let ty = ty.fold_with(&mut ClosureEraser { infcx, depth: 0 });
|
||||
|
||||
match (ty.kind(), called_method_def_id) {
|
||||
// We don't want the regular output for `fn`s because it includes its path in
|
||||
@@ -467,6 +475,25 @@ pub fn emit_inference_failure_err(
|
||||
term: Term<'tcx>,
|
||||
error_code: TypeAnnotationNeeded,
|
||||
should_label_span: bool,
|
||||
) -> Diag<'a> {
|
||||
self.emit_inference_failure_err_with_type_hint(
|
||||
body_def_id,
|
||||
failure_span,
|
||||
term,
|
||||
error_code,
|
||||
should_label_span,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn emit_inference_failure_err_with_type_hint(
|
||||
&self,
|
||||
body_def_id: LocalDefId,
|
||||
failure_span: Span,
|
||||
term: Term<'tcx>,
|
||||
error_code: TypeAnnotationNeeded,
|
||||
should_label_span: bool,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
) -> Diag<'a> {
|
||||
let term = self.resolve_vars_if_possible(term);
|
||||
let arg_data = self
|
||||
@@ -479,7 +506,7 @@ pub fn emit_inference_failure_err(
|
||||
return self.bad_inference_failure_err(failure_span, arg_data, error_code);
|
||||
};
|
||||
|
||||
let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, term);
|
||||
let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, term, ty);
|
||||
if let Some(body) = self.tcx.hir_maybe_body_owned_by(
|
||||
self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local(),
|
||||
) {
|
||||
@@ -779,10 +806,20 @@ fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String, Op
|
||||
| InferSourceKind::ClosureReturn { ty, .. } => {
|
||||
if ty.is_closure() {
|
||||
("closure", closure_as_fn_str(infcx, ty), long_ty_path)
|
||||
} else if !ty.is_ty_or_numeric_infer() {
|
||||
("normal", infcx.tcx.short_string(ty, &mut long_ty_path), long_ty_path)
|
||||
} else {
|
||||
} else if ty.is_ty_or_numeric_infer()
|
||||
|| ty.is_primitive()
|
||||
|| matches!(
|
||||
ty.kind(),
|
||||
ty::Adt(_, args)
|
||||
if args.types().count() == 0 && args.consts().count() == 0
|
||||
)
|
||||
{
|
||||
// `ty` is either `_`, a primitive type like `u32` or a type with no type or
|
||||
// const parameters. We will not mention the type in the main inference error
|
||||
// message.
|
||||
("other", String::new(), long_ty_path)
|
||||
} else {
|
||||
("normal", infcx.tcx.short_string(ty, &mut long_ty_path), long_ty_path)
|
||||
}
|
||||
}
|
||||
// FIXME: We should be able to add some additional info here.
|
||||
@@ -815,6 +852,7 @@ struct FindInferSourceVisitor<'a, 'tcx> {
|
||||
typeck_results: &'a TypeckResults<'tcx>,
|
||||
|
||||
target: Term<'tcx>,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
|
||||
attempt: usize,
|
||||
infer_source_cost: usize,
|
||||
@@ -826,12 +864,14 @@ fn new(
|
||||
tecx: &'a TypeErrCtxt<'a, 'tcx>,
|
||||
typeck_results: &'a TypeckResults<'tcx>,
|
||||
target: Term<'tcx>,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
) -> Self {
|
||||
FindInferSourceVisitor {
|
||||
tecx,
|
||||
typeck_results,
|
||||
|
||||
target,
|
||||
ty,
|
||||
|
||||
attempt: 0,
|
||||
infer_source_cost: usize::MAX,
|
||||
@@ -1213,7 +1253,7 @@ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
|
||||
fn visit_local(&mut self, local: &'tcx LetStmt<'tcx>) {
|
||||
intravisit::walk_local(self, local);
|
||||
|
||||
if let Some(ty) = self.opt_node_type(local.hir_id) {
|
||||
if let Some(mut ty) = self.opt_node_type(local.hir_id) {
|
||||
if self.generic_arg_contains_target(ty.into()) {
|
||||
fn get_did(
|
||||
typeck_results: &TypeckResults<'_>,
|
||||
@@ -1241,7 +1281,11 @@ fn get_did(
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(t) = self.ty
|
||||
&& ty.has_infer()
|
||||
{
|
||||
ty = t;
|
||||
}
|
||||
if let LocalSource::Normal = local.source
|
||||
&& local.ty.is_none()
|
||||
{
|
||||
|
||||
@@ -246,12 +246,37 @@ pub(super) fn maybe_report_ambiguity(
|
||||
.find(|s| s.has_non_region_infer());
|
||||
|
||||
let mut err = if let Some(term) = term {
|
||||
self.emit_inference_failure_err(
|
||||
let candidates: Vec<_> = self
|
||||
.tcx
|
||||
.all_impls(trait_pred.def_id())
|
||||
.filter_map(|def_id| {
|
||||
let imp = self.tcx.impl_trait_header(def_id);
|
||||
if imp.polarity != ty::ImplPolarity::Positive
|
||||
|| !self.tcx.is_user_visible_dep(def_id.krate)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let imp = imp.trait_ref.skip_binder();
|
||||
if imp
|
||||
.with_replaced_self_ty(self.tcx, trait_pred.skip_binder().self_ty())
|
||||
== trait_pred.skip_binder().trait_ref
|
||||
{
|
||||
Some(imp.self_ty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
self.emit_inference_failure_err_with_type_hint(
|
||||
obligation.cause.body_id,
|
||||
span,
|
||||
term,
|
||||
TypeAnnotationNeeded::E0283,
|
||||
true,
|
||||
match &candidates[..] {
|
||||
[candidate] => Some(*candidate),
|
||||
_ => None,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
struct_span_code_err!(
|
||||
|
||||
@@ -2251,6 +2251,16 @@ pub(super) fn report_similar_impl_candidates(
|
||||
if candidates.is_empty() {
|
||||
return false;
|
||||
}
|
||||
let mut specific_candidates = candidates.clone();
|
||||
specific_candidates.retain(|(tr, _)| {
|
||||
tr.with_replaced_self_ty(self.tcx, trait_pred.skip_binder().self_ty())
|
||||
== trait_pred.skip_binder().trait_ref
|
||||
});
|
||||
if !specific_candidates.is_empty() {
|
||||
// We have found a subset of impls that fully satisfy the expected trait, only
|
||||
// mention those types.
|
||||
candidates = specific_candidates;
|
||||
}
|
||||
if let &[(cand, def_id)] = &candidates[..] {
|
||||
if self.tcx.is_diagnostic_item(sym::FromResidual, cand.def_id)
|
||||
&& !self.tcx.features().enabled(sym::try_trait_v2)
|
||||
|
||||
@@ -58,7 +58,8 @@ fn recurse_build<'tcx>(
|
||||
}
|
||||
&ExprKind::Literal { lit, neg } => {
|
||||
let sp = node.span;
|
||||
match tcx.at(sp).lit_to_const(LitToConstInput { lit: lit.node, ty: node.ty, neg }) {
|
||||
match tcx.at(sp).lit_to_const(LitToConstInput { lit: lit.node, ty: Some(node.ty), neg })
|
||||
{
|
||||
Some(value) => ty::Const::new_value(tcx, value.valtree, value.ty),
|
||||
None => ty::Const::new_misc_error(tcx),
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
/// ```
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
#[stable(feature = "wake_trait", since = "1.51.0")]
|
||||
#[rustc_diagnostic_item = "Wake"]
|
||||
pub trait Wake {
|
||||
/// Wake this task.
|
||||
#[stable(feature = "wake_trait", since = "1.51.0")]
|
||||
|
||||
@@ -357,6 +357,7 @@ fn assert_fields_are_eq(&self) {}
|
||||
}
|
||||
|
||||
/// Derive macro generating an impl of the trait [`Eq`].
|
||||
/// The behavior of this macro is described in detail [here](Eq#derivable).
|
||||
#[rustc_builtin_macro]
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow_internal_unstable(core_intrinsics, derive_eq_internals, structural_match)]
|
||||
|
||||
@@ -823,7 +823,7 @@ fn enc_16lsd<const OFFSET: usize>(buf: &mut [MaybeUninit<u8>], n: u64) {
|
||||
let mut remain = n;
|
||||
|
||||
// Format per four digits from the lookup table.
|
||||
for quad_index in (0..4).rev() {
|
||||
for quad_index in (1..4).rev() {
|
||||
// pull two pairs
|
||||
let quad = remain % 1_00_00;
|
||||
remain /= 1_00_00;
|
||||
@@ -834,6 +834,14 @@ fn enc_16lsd<const OFFSET: usize>(buf: &mut [MaybeUninit<u8>], n: u64) {
|
||||
buf[quad_index * 4 + OFFSET + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]);
|
||||
buf[quad_index * 4 + OFFSET + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]);
|
||||
}
|
||||
|
||||
// final two pairs
|
||||
let pair1 = (remain / 100) as usize;
|
||||
let pair2 = (remain % 100) as usize;
|
||||
buf[OFFSET + 0].write(DECIMAL_PAIRS[pair1 * 2 + 0]);
|
||||
buf[OFFSET + 1].write(DECIMAL_PAIRS[pair1 * 2 + 1]);
|
||||
buf[OFFSET + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]);
|
||||
buf[OFFSET + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]);
|
||||
}
|
||||
|
||||
/// Euclidean division plus remainder with constant 1E16 basically consumes 16
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Representation of a float as the significant digits and exponent.
|
||||
|
||||
use dec2flt::float::RawFloat;
|
||||
use dec2flt::Lemire;
|
||||
use dec2flt::fpu::set_precision;
|
||||
|
||||
use crate::num::imp::dec2flt;
|
||||
@@ -36,7 +36,7 @@ pub struct Decimal {
|
||||
impl Decimal {
|
||||
/// Detect if the float can be accurately reconstructed from native floats.
|
||||
#[inline]
|
||||
fn can_use_fast_path<F: RawFloat>(&self) -> bool {
|
||||
fn can_use_fast_path<F: Lemire>(&self) -> bool {
|
||||
F::MIN_EXPONENT_FAST_PATH <= self.exponent
|
||||
&& self.exponent <= F::MAX_EXPONENT_DISGUISED_FAST_PATH
|
||||
&& self.mantissa <= F::MAX_MANTISSA_FAST_PATH
|
||||
@@ -53,7 +53,7 @@ fn can_use_fast_path<F: RawFloat>(&self) -> bool {
|
||||
///
|
||||
/// There is an exception: disguised fast-path cases, where we can shift
|
||||
/// powers-of-10 from the exponent to the significant digits.
|
||||
pub fn try_fast_path<F: RawFloat>(&self) -> Option<F> {
|
||||
pub fn try_fast_path<F: Lemire>(&self) -> Option<F> {
|
||||
// Here we need to work around <https://github.com/rust-lang/rust/issues/114479>.
|
||||
// The fast path crucially depends on arithmetic being rounded to the correct number of bits
|
||||
// without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
//! Implementation of the Eisel-Lemire algorithm.
|
||||
|
||||
use dec2flt::common::BiasedFp;
|
||||
use dec2flt::float::RawFloat;
|
||||
use dec2flt::table::{LARGEST_POWER_OF_FIVE, POWER_OF_FIVE_128, SMALLEST_POWER_OF_FIVE};
|
||||
|
||||
use crate::num::imp::dec2flt;
|
||||
use crate::num::imp::{Float, dec2flt};
|
||||
|
||||
/// Compute w * 10^q using an extended-precision float representation.
|
||||
///
|
||||
@@ -24,7 +23,7 @@
|
||||
/// at a Gigabyte per Second" in section 5, "Fast Algorithm", and
|
||||
/// section 6, "Exact Numbers And Ties", available online:
|
||||
/// <https://arxiv.org/abs/2101.11408.pdf>.
|
||||
pub fn compute_float<F: RawFloat>(q: i64, mut w: u64) -> BiasedFp {
|
||||
pub fn compute_float<F: Float>(q: i64, mut w: u64) -> BiasedFp {
|
||||
let fp_zero = BiasedFp::zero_pow2(0);
|
||||
let fp_inf = BiasedFp::zero_pow2(F::INFINITE_POWER);
|
||||
let fp_error = BiasedFp::zero_pow2(-1);
|
||||
|
||||
@@ -88,24 +88,104 @@
|
||||
)]
|
||||
|
||||
use common::BiasedFp;
|
||||
use float::RawFloat;
|
||||
use lemire::compute_float;
|
||||
use parse::{parse_inf_nan, parse_number};
|
||||
use slow::parse_long_mantissa;
|
||||
|
||||
use crate::f64;
|
||||
use crate::num::ParseFloatError;
|
||||
use crate::num::float_parse::FloatErrorKind;
|
||||
use crate::num::imp::FloatExt;
|
||||
|
||||
mod common;
|
||||
pub mod decimal;
|
||||
pub mod decimal_seq;
|
||||
mod fpu;
|
||||
mod slow;
|
||||
mod table;
|
||||
// float is used in flt2dec, and all are used in unit tests.
|
||||
pub mod float;
|
||||
pub mod lemire;
|
||||
pub mod parse;
|
||||
mod slow;
|
||||
mod table;
|
||||
|
||||
/// Extension to `Float` that are necessary for parsing using the Lemire method.
|
||||
///
|
||||
/// See the parent module's doc comment for why this is necessary.
|
||||
///
|
||||
/// Not intended for use outside of the `dec2flt` module.
|
||||
#[doc(hidden)]
|
||||
pub trait Lemire: FloatExt {
|
||||
/// Maximum exponent for a fast path case, or `⌊(SIG_BITS+1)/log2(5)⌋`
|
||||
// assuming FLT_EVAL_METHOD = 0
|
||||
const MAX_EXPONENT_FAST_PATH: i64 = {
|
||||
let log2_5 = f64::consts::LOG2_10 - 1.0;
|
||||
(Self::SIG_TOTAL_BITS as f64 / log2_5) as i64
|
||||
};
|
||||
|
||||
/// Minimum exponent for a fast path case, or `-⌊(SIG_BITS+1)/log2(5)⌋`
|
||||
const MIN_EXPONENT_FAST_PATH: i64 = -Self::MAX_EXPONENT_FAST_PATH;
|
||||
|
||||
/// Maximum exponent that can be represented for a disguised-fast path case.
|
||||
/// This is `MAX_EXPONENT_FAST_PATH + ⌊(SIG_BITS+1)/log2(10)⌋`
|
||||
const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 =
|
||||
Self::MAX_EXPONENT_FAST_PATH + (Self::SIG_TOTAL_BITS as f64 / f64::consts::LOG2_10) as i64;
|
||||
|
||||
/// Maximum mantissa for the fast-path (`1 << 53` for f64).
|
||||
const MAX_MANTISSA_FAST_PATH: u64 = 1 << Self::SIG_TOTAL_BITS;
|
||||
|
||||
/// Gets a small power-of-ten for fast-path multiplication.
|
||||
fn pow10_fast_path(exponent: usize) -> Self;
|
||||
|
||||
/// Converts integer into float through an as cast.
|
||||
/// This is only called in the fast-path algorithm, and therefore
|
||||
/// will not lose precision, since the value will always have
|
||||
/// only if the value is <= Self::MAX_MANTISSA_FAST_PATH.
|
||||
fn from_u64(v: u64) -> Self;
|
||||
}
|
||||
|
||||
#[cfg(target_has_reliable_f16)]
|
||||
impl Lemire for f16 {
|
||||
fn pow10_fast_path(exponent: usize) -> Self {
|
||||
#[allow(clippy::use_self)]
|
||||
const TABLE: [f16; 8] = [1e0, 1e1, 1e2, 1e3, 1e4, 0.0, 0.0, 0.];
|
||||
TABLE[exponent & 7]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_u64(v: u64) -> Self {
|
||||
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
|
||||
v as _
|
||||
}
|
||||
}
|
||||
|
||||
impl Lemire for f32 {
|
||||
fn pow10_fast_path(exponent: usize) -> Self {
|
||||
#[allow(clippy::use_self)]
|
||||
const TABLE: [f32; 16] =
|
||||
[1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.];
|
||||
TABLE[exponent & 15]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_u64(v: u64) -> Self {
|
||||
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
|
||||
v as _
|
||||
}
|
||||
}
|
||||
|
||||
impl Lemire for f64 {
|
||||
fn pow10_fast_path(exponent: usize) -> Self {
|
||||
const TABLE: [f64; 32] = [
|
||||
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
|
||||
1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0.,
|
||||
];
|
||||
TABLE[exponent & 31]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_u64(v: u64) -> Self {
|
||||
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
|
||||
v as _
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn pfe_empty() -> ParseFloatError {
|
||||
@@ -120,7 +200,7 @@ pub fn pfe_invalid() -> ParseFloatError {
|
||||
}
|
||||
|
||||
/// Converts a `BiasedFp` to the closest machine float type.
|
||||
fn biased_fp_to_float<F: RawFloat>(x: BiasedFp) -> F {
|
||||
fn biased_fp_to_float<F: FloatExt>(x: BiasedFp) -> F {
|
||||
let mut word = x.m;
|
||||
word |= (x.p_biased as u64) << F::SIG_BITS;
|
||||
F::from_u64_bits(word)
|
||||
@@ -128,7 +208,7 @@ fn biased_fp_to_float<F: RawFloat>(x: BiasedFp) -> F {
|
||||
|
||||
/// Converts a decimal string into a floating point number.
|
||||
#[inline(always)] // Will be inlined into a function with `#[inline(never)]`, see above
|
||||
pub fn dec2flt<F: RawFloat>(s: &str) -> Result<F, ParseFloatError> {
|
||||
pub fn dec2flt<F: Lemire>(s: &str) -> Result<F, ParseFloatError> {
|
||||
let mut s = s.as_bytes();
|
||||
let Some(&c) = s.first() else { return Err(pfe_empty()) };
|
||||
let negative = c == b'-';
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
use dec2flt::common::{ByteSlice, is_8digits};
|
||||
use dec2flt::decimal::Decimal;
|
||||
use dec2flt::float::RawFloat;
|
||||
|
||||
use crate::num::imp::dec2flt;
|
||||
use crate::num::imp::{Float, dec2flt};
|
||||
|
||||
const MIN_19DIGIT_INT: u64 = 100_0000_0000_0000_0000;
|
||||
|
||||
@@ -197,7 +196,7 @@ pub fn parse_number(s: &[u8]) -> Option<Decimal> {
|
||||
}
|
||||
|
||||
/// Try to parse a special, non-finite float.
|
||||
pub(crate) fn parse_inf_nan<F: RawFloat>(s: &[u8], negative: bool) -> Option<F> {
|
||||
pub(crate) fn parse_inf_nan<F: Float>(s: &[u8], negative: bool) -> Option<F> {
|
||||
// Since a valid string has at most the length 8, we can load
|
||||
// all relevant characters into a u64 and work from there.
|
||||
// This also generates much better code.
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
use dec2flt::common::BiasedFp;
|
||||
use dec2flt::decimal_seq::{DecimalSeq, parse_decimal_seq};
|
||||
use dec2flt::float::RawFloat;
|
||||
|
||||
use crate::num::imp::dec2flt;
|
||||
use crate::num::imp::{Float, dec2flt};
|
||||
|
||||
/// Parse the significant digits and biased, binary exponent of a float.
|
||||
///
|
||||
@@ -25,7 +24,7 @@
|
||||
///
|
||||
/// The algorithms described here are based on "Processing Long Numbers Quickly",
|
||||
/// available here: <https://arxiv.org/pdf/2101.11408.pdf#section.11>.
|
||||
pub(crate) fn parse_long_mantissa<F: RawFloat>(s: &[u8]) -> BiasedFp {
|
||||
pub(crate) fn parse_long_mantissa<F: Float>(s: &[u8]) -> BiasedFp {
|
||||
const MAX_SHIFT: usize = 60;
|
||||
const NUM_POWERS: usize = 19;
|
||||
const POWERS: [u8; 19] =
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! Decodes a floating-point value into individual parts and error ranges.
|
||||
|
||||
use crate::num::FpCategory;
|
||||
use crate::num::imp::dec2flt::float::RawFloat;
|
||||
use crate::num::imp::FloatExt;
|
||||
|
||||
/// Decoded unsigned finite value, such that:
|
||||
///
|
||||
@@ -40,7 +40,7 @@ pub enum FullDecoded {
|
||||
}
|
||||
|
||||
/// A floating point type which can be `decode`d.
|
||||
pub trait DecodableFloat: RawFloat + Copy {
|
||||
pub trait DecodableFloat: FloatExt + Copy {
|
||||
/// The minimum positive normalized value.
|
||||
fn min_pos_norm_value() -> Self;
|
||||
}
|
||||
|
||||
@@ -16,3 +16,6 @@
|
||||
pub(crate) mod int_sqrt;
|
||||
pub(crate) mod libm;
|
||||
pub(crate) mod overflow_panic;
|
||||
mod traits;
|
||||
|
||||
pub use traits::{Float, FloatExt, Int};
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
//! Helper trait for generic float types.
|
||||
//! Numeric traits used for internal implementations.
|
||||
|
||||
use core::f64;
|
||||
#![doc(hidden)]
|
||||
#![unstable(
|
||||
feature = "num_internals",
|
||||
reason = "internal routines only exposed for testing",
|
||||
issue = "none"
|
||||
)]
|
||||
|
||||
use crate::fmt::{Debug, LowerExp};
|
||||
use crate::num::FpCategory;
|
||||
use crate::ops::{self, Add, Div, Mul, Neg};
|
||||
use crate::{f64, fmt, ops};
|
||||
|
||||
/// Lossy `as` casting between two types.
|
||||
pub trait CastInto<T: Copy>: Copy {
|
||||
@@ -12,11 +16,11 @@ pub trait CastInto<T: Copy>: Copy {
|
||||
}
|
||||
|
||||
/// Collection of traits that allow us to be generic over integer size.
|
||||
pub trait Integer:
|
||||
pub trait Int:
|
||||
Sized
|
||||
+ Clone
|
||||
+ Copy
|
||||
+ Debug
|
||||
+ fmt::Debug
|
||||
+ ops::Shr<u32, Output = Self>
|
||||
+ ops::Shl<u32, Output = Self>
|
||||
+ ops::BitAnd<Output = Self>
|
||||
@@ -37,7 +41,7 @@ fn cast(self) -> i16 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Integer for $ty {
|
||||
impl Int for $ty {
|
||||
const ZERO: Self = 0;
|
||||
const ONE: Self = 1;
|
||||
}
|
||||
@@ -48,27 +52,22 @@ impl Integer for $ty {
|
||||
int!(u16, u32, u64);
|
||||
|
||||
/// A helper trait to avoid duplicating basically all the conversion code for IEEE floats.
|
||||
///
|
||||
/// See the parent module's doc comment for why this is necessary.
|
||||
///
|
||||
/// Should **never ever** be implemented for other types or be used outside the `dec2flt` module.
|
||||
#[doc(hidden)]
|
||||
pub trait RawFloat:
|
||||
pub trait Float:
|
||||
Sized
|
||||
+ Div<Output = Self>
|
||||
+ Neg<Output = Self>
|
||||
+ Mul<Output = Self>
|
||||
+ Add<Output = Self>
|
||||
+ LowerExp
|
||||
+ ops::Div<Output = Self>
|
||||
+ ops::Neg<Output = Self>
|
||||
+ ops::Mul<Output = Self>
|
||||
+ ops::Add<Output = Self>
|
||||
+ fmt::Debug
|
||||
+ PartialEq
|
||||
+ PartialOrd
|
||||
+ Default
|
||||
+ Clone
|
||||
+ Copy
|
||||
+ Debug
|
||||
{
|
||||
/// The unsigned integer with the same size as the float
|
||||
type Int: Integer + Into<u64>;
|
||||
type Int: Int + Into<u64>;
|
||||
|
||||
/* general constants */
|
||||
|
||||
@@ -128,8 +127,6 @@ pub trait RawFloat:
|
||||
const MIN_EXPONENT_ROUND_TO_EVEN: i32;
|
||||
const MAX_EXPONENT_ROUND_TO_EVEN: i32;
|
||||
|
||||
/* limits related to Fast pathing */
|
||||
|
||||
/// Largest decimal exponent for a non-infinite value.
|
||||
///
|
||||
/// This is the max exponent in binary converted to the max exponent in decimal. Allows fast
|
||||
@@ -151,41 +148,19 @@ pub trait RawFloat:
|
||||
/// compile time since intermediates exceed the range of an `f64`.
|
||||
const SMALLEST_POWER_OF_TEN: i32;
|
||||
|
||||
/// Maximum exponent for a fast path case, or `⌊(SIG_BITS+1)/log2(5)⌋`
|
||||
// assuming FLT_EVAL_METHOD = 0
|
||||
const MAX_EXPONENT_FAST_PATH: i64 = {
|
||||
let log2_5 = f64::consts::LOG2_10 - 1.0;
|
||||
(Self::SIG_TOTAL_BITS as f64 / log2_5) as i64
|
||||
};
|
||||
|
||||
/// Minimum exponent for a fast path case, or `-⌊(SIG_BITS+1)/log2(5)⌋`
|
||||
const MIN_EXPONENT_FAST_PATH: i64 = -Self::MAX_EXPONENT_FAST_PATH;
|
||||
|
||||
/// Maximum exponent that can be represented for a disguised-fast path case.
|
||||
/// This is `MAX_EXPONENT_FAST_PATH + ⌊(SIG_BITS+1)/log2(10)⌋`
|
||||
const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 =
|
||||
Self::MAX_EXPONENT_FAST_PATH + (Self::SIG_TOTAL_BITS as f64 / f64::consts::LOG2_10) as i64;
|
||||
|
||||
/// Maximum mantissa for the fast-path (`1 << 53` for f64).
|
||||
const MAX_MANTISSA_FAST_PATH: u64 = 1 << Self::SIG_TOTAL_BITS;
|
||||
|
||||
/// Converts integer into float through an as cast.
|
||||
/// This is only called in the fast-path algorithm, and therefore
|
||||
/// will not lose precision, since the value will always have
|
||||
/// only if the value is <= Self::MAX_MANTISSA_FAST_PATH.
|
||||
fn from_u64(v: u64) -> Self;
|
||||
|
||||
/// Performs a raw transmutation from an integer.
|
||||
fn from_u64_bits(v: u64) -> Self;
|
||||
|
||||
/// Gets a small power-of-ten for fast-path multiplication.
|
||||
fn pow10_fast_path(exponent: usize) -> Self;
|
||||
|
||||
/// Returns the category that this number falls into.
|
||||
fn classify(self) -> FpCategory;
|
||||
|
||||
/// Transmute to the integer representation
|
||||
fn to_bits(self) -> Self::Int;
|
||||
}
|
||||
|
||||
/// Items that ideally would be on `Float`, but don't apply to all float types because they
|
||||
/// rely on the mantissa fitting into a `u64` (which isn't true for `f128`).
|
||||
#[doc(hidden)]
|
||||
pub trait FloatExt: Float {
|
||||
/// Performs a raw transmutation from an integer.
|
||||
fn from_u64_bits(v: u64) -> Self;
|
||||
|
||||
/// Returns the mantissa, exponent and sign as integers.
|
||||
///
|
||||
@@ -219,7 +194,7 @@ const fn pow2_to_pow10(a: i64) -> i64 {
|
||||
}
|
||||
|
||||
#[cfg(target_has_reliable_f16)]
|
||||
impl RawFloat for f16 {
|
||||
impl Float for f16 {
|
||||
type Int = u16;
|
||||
|
||||
const INFINITY: Self = Self::INFINITY;
|
||||
@@ -236,23 +211,6 @@ impl RawFloat for f16 {
|
||||
const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 5;
|
||||
const SMALLEST_POWER_OF_TEN: i32 = -27;
|
||||
|
||||
#[inline]
|
||||
fn from_u64(v: u64) -> Self {
|
||||
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
|
||||
v as _
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_u64_bits(v: u64) -> Self {
|
||||
Self::from_bits((v & 0xFFFF) as u16)
|
||||
}
|
||||
|
||||
fn pow10_fast_path(exponent: usize) -> Self {
|
||||
#[allow(clippy::use_self)]
|
||||
const TABLE: [f16; 8] = [1e0, 1e1, 1e2, 1e3, 1e4, 0.0, 0.0, 0.];
|
||||
TABLE[exponent & 7]
|
||||
}
|
||||
|
||||
fn to_bits(self) -> Self::Int {
|
||||
self.to_bits()
|
||||
}
|
||||
@@ -262,7 +220,15 @@ fn classify(self) -> FpCategory {
|
||||
}
|
||||
}
|
||||
|
||||
impl RawFloat for f32 {
|
||||
#[cfg(target_has_reliable_f16)]
|
||||
impl FloatExt for f16 {
|
||||
#[inline]
|
||||
fn from_u64_bits(v: u64) -> Self {
|
||||
Self::from_bits((v & 0xFFFF) as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl Float for f32 {
|
||||
type Int = u32;
|
||||
|
||||
const INFINITY: Self = f32::INFINITY;
|
||||
@@ -279,24 +245,6 @@ impl RawFloat for f32 {
|
||||
const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10;
|
||||
const SMALLEST_POWER_OF_TEN: i32 = -65;
|
||||
|
||||
#[inline]
|
||||
fn from_u64(v: u64) -> Self {
|
||||
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
|
||||
v as _
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_u64_bits(v: u64) -> Self {
|
||||
f32::from_bits((v & 0xFFFFFFFF) as u32)
|
||||
}
|
||||
|
||||
fn pow10_fast_path(exponent: usize) -> Self {
|
||||
#[allow(clippy::use_self)]
|
||||
const TABLE: [f32; 16] =
|
||||
[1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.];
|
||||
TABLE[exponent & 15]
|
||||
}
|
||||
|
||||
fn to_bits(self) -> Self::Int {
|
||||
self.to_bits()
|
||||
}
|
||||
@@ -306,7 +254,14 @@ fn classify(self) -> FpCategory {
|
||||
}
|
||||
}
|
||||
|
||||
impl RawFloat for f64 {
|
||||
impl FloatExt for f32 {
|
||||
#[inline]
|
||||
fn from_u64_bits(v: u64) -> Self {
|
||||
f32::from_bits((v & 0xFFFFFFFF) as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Float for f64 {
|
||||
type Int = u64;
|
||||
|
||||
const INFINITY: Self = Self::INFINITY;
|
||||
@@ -323,25 +278,6 @@ impl RawFloat for f64 {
|
||||
const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23;
|
||||
const SMALLEST_POWER_OF_TEN: i32 = -342;
|
||||
|
||||
#[inline]
|
||||
fn from_u64(v: u64) -> Self {
|
||||
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
|
||||
v as _
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_u64_bits(v: u64) -> Self {
|
||||
f64::from_bits(v)
|
||||
}
|
||||
|
||||
fn pow10_fast_path(exponent: usize) -> Self {
|
||||
const TABLE: [f64; 32] = [
|
||||
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
|
||||
1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0.,
|
||||
];
|
||||
TABLE[exponent & 31]
|
||||
}
|
||||
|
||||
fn to_bits(self) -> Self::Int {
|
||||
self.to_bits()
|
||||
}
|
||||
@@ -350,3 +286,10 @@ fn classify(self) -> FpCategory {
|
||||
self.classify()
|
||||
}
|
||||
}
|
||||
|
||||
impl FloatExt for f64 {
|
||||
#[inline]
|
||||
fn from_u64_bits(v: u64) -> Self {
|
||||
f64::from_bits(v)
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,7 @@
|
||||
#![feature(next_index)]
|
||||
#![feature(non_exhaustive_omitted_patterns_lint)]
|
||||
#![feature(nonzero_from_str_radix)]
|
||||
#![feature(num_internals)]
|
||||
#![feature(numfmt)]
|
||||
#![feature(one_sided_range)]
|
||||
#![feature(panic_internals)]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use core::num::imp::dec2flt::float::RawFloat;
|
||||
use core::num::imp::dec2flt::Lemire;
|
||||
use core::num::imp::{Float, FloatExt};
|
||||
|
||||
use crate::num::{ldexp_f32, ldexp_f64};
|
||||
|
||||
@@ -56,57 +57,60 @@ fn test_f64_integer_decode() {
|
||||
#[test]
|
||||
#[cfg(target_has_reliable_f16)]
|
||||
fn test_f16_consts() {
|
||||
assert_eq!(<f16 as RawFloat>::INFINITY, f16::INFINITY);
|
||||
assert_eq!(<f16 as RawFloat>::NEG_INFINITY, -f16::INFINITY);
|
||||
assert_eq!(<f16 as RawFloat>::NAN.to_bits(), f16::NAN.to_bits());
|
||||
assert_eq!(<f16 as RawFloat>::NEG_NAN.to_bits(), (-f16::NAN).to_bits());
|
||||
assert_eq!(<f16 as RawFloat>::SIG_BITS, 10);
|
||||
assert_eq!(<f16 as RawFloat>::MIN_EXPONENT_ROUND_TO_EVEN, -22);
|
||||
assert_eq!(<f16 as RawFloat>::MAX_EXPONENT_ROUND_TO_EVEN, 5);
|
||||
assert_eq!(<f16 as RawFloat>::MIN_EXPONENT_FAST_PATH, -4);
|
||||
assert_eq!(<f16 as RawFloat>::MAX_EXPONENT_FAST_PATH, 4);
|
||||
assert_eq!(<f16 as RawFloat>::MAX_EXPONENT_DISGUISED_FAST_PATH, 7);
|
||||
assert_eq!(<f16 as RawFloat>::EXP_MIN, -14);
|
||||
assert_eq!(<f16 as RawFloat>::EXP_SAT, 0x1f);
|
||||
assert_eq!(<f16 as RawFloat>::SMALLEST_POWER_OF_TEN, -27);
|
||||
assert_eq!(<f16 as RawFloat>::LARGEST_POWER_OF_TEN, 4);
|
||||
assert_eq!(<f16 as RawFloat>::MAX_MANTISSA_FAST_PATH, 2048);
|
||||
assert_eq!(<f16 as Float>::INFINITY, f16::INFINITY);
|
||||
assert_eq!(<f16 as Float>::NEG_INFINITY, -f16::INFINITY);
|
||||
assert_eq!(<f16 as Float>::NAN.to_bits(), f16::NAN.to_bits());
|
||||
assert_eq!(<f16 as Float>::NEG_NAN.to_bits(), (-f16::NAN).to_bits());
|
||||
assert_eq!(<f16 as Float>::SIG_BITS, 10);
|
||||
assert_eq!(<f16 as Float>::MIN_EXPONENT_ROUND_TO_EVEN, -22);
|
||||
assert_eq!(<f16 as Float>::MAX_EXPONENT_ROUND_TO_EVEN, 5);
|
||||
assert_eq!(<f16 as Float>::EXP_MIN, -14);
|
||||
assert_eq!(<f16 as Float>::EXP_SAT, 0x1f);
|
||||
assert_eq!(<f16 as Float>::SMALLEST_POWER_OF_TEN, -27);
|
||||
assert_eq!(<f16 as Float>::LARGEST_POWER_OF_TEN, 4);
|
||||
|
||||
assert_eq!(<f16 as Lemire>::MIN_EXPONENT_FAST_PATH, -4);
|
||||
assert_eq!(<f16 as Lemire>::MAX_EXPONENT_FAST_PATH, 4);
|
||||
assert_eq!(<f16 as Lemire>::MAX_EXPONENT_DISGUISED_FAST_PATH, 7);
|
||||
assert_eq!(<f16 as Lemire>::MAX_MANTISSA_FAST_PATH, 2048);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_f32_consts() {
|
||||
assert_eq!(<f32 as RawFloat>::INFINITY, f32::INFINITY);
|
||||
assert_eq!(<f32 as RawFloat>::NEG_INFINITY, -f32::INFINITY);
|
||||
assert_eq!(<f32 as RawFloat>::NAN.to_bits(), f32::NAN.to_bits());
|
||||
assert_eq!(<f32 as RawFloat>::NEG_NAN.to_bits(), (-f32::NAN).to_bits());
|
||||
assert_eq!(<f32 as RawFloat>::SIG_BITS, 23);
|
||||
assert_eq!(<f32 as RawFloat>::MIN_EXPONENT_ROUND_TO_EVEN, -17);
|
||||
assert_eq!(<f32 as RawFloat>::MAX_EXPONENT_ROUND_TO_EVEN, 10);
|
||||
assert_eq!(<f32 as RawFloat>::MIN_EXPONENT_FAST_PATH, -10);
|
||||
assert_eq!(<f32 as RawFloat>::MAX_EXPONENT_FAST_PATH, 10);
|
||||
assert_eq!(<f32 as RawFloat>::MAX_EXPONENT_DISGUISED_FAST_PATH, 17);
|
||||
assert_eq!(<f32 as RawFloat>::EXP_MIN, -126);
|
||||
assert_eq!(<f32 as RawFloat>::EXP_SAT, 0xff);
|
||||
assert_eq!(<f32 as RawFloat>::SMALLEST_POWER_OF_TEN, -65);
|
||||
assert_eq!(<f32 as RawFloat>::LARGEST_POWER_OF_TEN, 38);
|
||||
assert_eq!(<f32 as RawFloat>::MAX_MANTISSA_FAST_PATH, 16777216);
|
||||
assert_eq!(<f32 as Float>::INFINITY, f32::INFINITY);
|
||||
assert_eq!(<f32 as Float>::NEG_INFINITY, -f32::INFINITY);
|
||||
assert_eq!(<f32 as Float>::NAN.to_bits(), f32::NAN.to_bits());
|
||||
assert_eq!(<f32 as Float>::NEG_NAN.to_bits(), (-f32::NAN).to_bits());
|
||||
assert_eq!(<f32 as Float>::SIG_BITS, 23);
|
||||
assert_eq!(<f32 as Float>::MIN_EXPONENT_ROUND_TO_EVEN, -17);
|
||||
assert_eq!(<f32 as Float>::MAX_EXPONENT_ROUND_TO_EVEN, 10);
|
||||
assert_eq!(<f32 as Float>::EXP_MIN, -126);
|
||||
assert_eq!(<f32 as Float>::EXP_SAT, 0xff);
|
||||
assert_eq!(<f32 as Float>::SMALLEST_POWER_OF_TEN, -65);
|
||||
assert_eq!(<f32 as Float>::LARGEST_POWER_OF_TEN, 38);
|
||||
|
||||
assert_eq!(<f32 as Lemire>::MIN_EXPONENT_FAST_PATH, -10);
|
||||
assert_eq!(<f32 as Lemire>::MAX_EXPONENT_FAST_PATH, 10);
|
||||
assert_eq!(<f32 as Lemire>::MAX_EXPONENT_DISGUISED_FAST_PATH, 17);
|
||||
assert_eq!(<f32 as Lemire>::MAX_MANTISSA_FAST_PATH, 16777216);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_f64_consts() {
|
||||
assert_eq!(<f64 as RawFloat>::INFINITY, f64::INFINITY);
|
||||
assert_eq!(<f64 as RawFloat>::NEG_INFINITY, -f64::INFINITY);
|
||||
assert_eq!(<f64 as RawFloat>::NAN.to_bits(), f64::NAN.to_bits());
|
||||
assert_eq!(<f64 as RawFloat>::NEG_NAN.to_bits(), (-f64::NAN).to_bits());
|
||||
assert_eq!(<f64 as RawFloat>::SIG_BITS, 52);
|
||||
assert_eq!(<f64 as RawFloat>::MIN_EXPONENT_ROUND_TO_EVEN, -4);
|
||||
assert_eq!(<f64 as RawFloat>::MAX_EXPONENT_ROUND_TO_EVEN, 23);
|
||||
assert_eq!(<f64 as RawFloat>::MIN_EXPONENT_FAST_PATH, -22);
|
||||
assert_eq!(<f64 as RawFloat>::MAX_EXPONENT_FAST_PATH, 22);
|
||||
assert_eq!(<f64 as RawFloat>::MAX_EXPONENT_DISGUISED_FAST_PATH, 37);
|
||||
assert_eq!(<f64 as RawFloat>::EXP_MIN, -1022);
|
||||
assert_eq!(<f64 as RawFloat>::EXP_SAT, 0x7ff);
|
||||
assert_eq!(<f64 as RawFloat>::SMALLEST_POWER_OF_TEN, -342);
|
||||
assert_eq!(<f64 as RawFloat>::LARGEST_POWER_OF_TEN, 308);
|
||||
assert_eq!(<f64 as RawFloat>::MAX_MANTISSA_FAST_PATH, 9007199254740992);
|
||||
assert_eq!(<f64 as Float>::INFINITY, f64::INFINITY);
|
||||
assert_eq!(<f64 as Float>::NEG_INFINITY, -f64::INFINITY);
|
||||
assert_eq!(<f64 as Float>::NAN.to_bits(), f64::NAN.to_bits());
|
||||
assert_eq!(<f64 as Float>::NEG_NAN.to_bits(), (-f64::NAN).to_bits());
|
||||
assert_eq!(<f64 as Float>::SIG_BITS, 52);
|
||||
assert_eq!(<f64 as Float>::MIN_EXPONENT_ROUND_TO_EVEN, -4);
|
||||
assert_eq!(<f64 as Float>::MAX_EXPONENT_ROUND_TO_EVEN, 23);
|
||||
assert_eq!(<f64 as Float>::EXP_MIN, -1022);
|
||||
assert_eq!(<f64 as Float>::EXP_SAT, 0x7ff);
|
||||
assert_eq!(<f64 as Float>::SMALLEST_POWER_OF_TEN, -342);
|
||||
assert_eq!(<f64 as Float>::LARGEST_POWER_OF_TEN, 308);
|
||||
|
||||
assert_eq!(<f64 as Lemire>::MIN_EXPONENT_FAST_PATH, -22);
|
||||
assert_eq!(<f64 as Lemire>::MAX_EXPONENT_FAST_PATH, 22);
|
||||
assert_eq!(<f64 as Lemire>::MAX_EXPONENT_DISGUISED_FAST_PATH, 37);
|
||||
assert_eq!(<f64 as Lemire>::MAX_MANTISSA_FAST_PATH, 9007199254740992);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use core::num::imp::dec2flt;
|
||||
use core::num::imp::{Float, dec2flt};
|
||||
|
||||
use dec2flt::float::RawFloat;
|
||||
use dec2flt::lemire::compute_float;
|
||||
|
||||
#[cfg(target_has_reliable_f16)]
|
||||
|
||||
@@ -79,4 +79,28 @@ fn main() {
|
||||
println!("cargo:rustc-cfg=backtrace_in_libstd");
|
||||
|
||||
println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
|
||||
|
||||
println!("cargo:rustc-check-cfg=cfg(vxworks_lt_25_09)");
|
||||
|
||||
if target_os == "vxworks" {
|
||||
match vxworks_version_code() {
|
||||
Some((major, minor)) if (major, minor) < (25, 9) => {
|
||||
println!("cargo:rustc-cfg=vxworks_lt_25_09");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the VxWorks release version from the environment variable set by the VxWorks build
|
||||
/// environment, in `(minor, patch)` form.
|
||||
fn vxworks_version_code() -> Option<(u32, u32)> {
|
||||
let version = env::var("WIND_RELEASE_ID").ok()?;
|
||||
|
||||
let mut pieces = version.trim().split(['.']);
|
||||
|
||||
let major: u32 = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0);
|
||||
let minor: u32 = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0);
|
||||
|
||||
Some((major, minor))
|
||||
}
|
||||
|
||||
@@ -69,24 +69,54 @@ fn st_rdev(&self) -> u64 {
|
||||
fn st_size(&self) -> u64 {
|
||||
self.as_inner().as_inner().st_size as u64
|
||||
}
|
||||
#[cfg(vxworks_lt_25_09)]
|
||||
fn st_atime(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_atime as i64
|
||||
}
|
||||
#[cfg(not(vxworks_lt_25_09))]
|
||||
fn st_atime(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_atim.tv_sec as i64
|
||||
}
|
||||
#[cfg(vxworks_lt_25_09)]
|
||||
fn st_atime_nsec(&self) -> i64 {
|
||||
0
|
||||
}
|
||||
#[cfg(not(vxworks_lt_25_09))]
|
||||
fn st_atime_nsec(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_atim.tv_nsec as i64
|
||||
}
|
||||
#[cfg(vxworks_lt_25_09)]
|
||||
fn st_mtime(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_mtime as i64
|
||||
}
|
||||
#[cfg(not(vxworks_lt_25_09))]
|
||||
fn st_mtime(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_mtim.tv_sec as i64
|
||||
}
|
||||
#[cfg(vxworks_lt_25_09)]
|
||||
fn st_mtime_nsec(&self) -> i64 {
|
||||
0
|
||||
}
|
||||
#[cfg(not(vxworks_lt_25_09))]
|
||||
fn st_mtime_nsec(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_mtim.tv_nsec as i64
|
||||
}
|
||||
#[cfg(vxworks_lt_25_09)]
|
||||
fn st_ctime(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_ctime as i64
|
||||
}
|
||||
#[cfg(not(vxworks_lt_25_09))]
|
||||
fn st_ctime(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_ctim.tv_sec as i64
|
||||
}
|
||||
#[cfg(vxworks_lt_25_09)]
|
||||
fn st_ctime_nsec(&self) -> i64 {
|
||||
0
|
||||
}
|
||||
#[cfg(not(vxworks_lt_25_09))]
|
||||
fn st_ctime_nsec(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_ctim.tv_nsec as i64
|
||||
}
|
||||
fn st_blksize(&self) -> u64 {
|
||||
self.as_inner().as_inner().st_blksize as u64
|
||||
}
|
||||
|
||||
@@ -623,6 +623,33 @@ pub fn same_channel(&self, other: &Sender<T>) -> bool {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the channel is disconnected.
|
||||
///
|
||||
/// Note that a return value of `false` does not guarantee the channel will
|
||||
/// remain connected. The channel may be disconnected immediately after this method
|
||||
/// returns, so a subsequent [`Sender::send`] may still fail with [`SendError`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(mpmc_channel)]
|
||||
///
|
||||
/// use std::sync::mpmc::channel;
|
||||
///
|
||||
/// let (tx, rx) = channel::<i32>();
|
||||
/// assert!(!tx.is_disconnected());
|
||||
/// drop(rx);
|
||||
/// assert!(tx.is_disconnected());
|
||||
/// ```
|
||||
#[unstable(feature = "mpmc_channel", issue = "126840")]
|
||||
pub fn is_disconnected(&self) -> bool {
|
||||
match &self.flavor {
|
||||
SenderFlavor::Array(chan) => chan.is_disconnected(),
|
||||
SenderFlavor::List(chan) => chan.is_disconnected(),
|
||||
SenderFlavor::Zero(chan) => chan.is_disconnected(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "mpmc_channel", issue = "126840")]
|
||||
@@ -1349,6 +1376,33 @@ pub fn same_channel(&self, other: &Receiver<T>) -> bool {
|
||||
pub fn iter(&self) -> Iter<'_, T> {
|
||||
Iter { rx: self }
|
||||
}
|
||||
|
||||
/// Returns `true` if the channel is disconnected.
|
||||
///
|
||||
/// Note that a return value of `false` does not guarantee the channel will
|
||||
/// remain connected. The channel may be disconnected immediately after this method
|
||||
/// returns, so a subsequent [`Receiver::recv`] may still fail with [`RecvError`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(mpmc_channel)]
|
||||
///
|
||||
/// use std::sync::mpmc::channel;
|
||||
///
|
||||
/// let (tx, rx) = channel::<i32>();
|
||||
/// assert!(!rx.is_disconnected());
|
||||
/// drop(tx);
|
||||
/// assert!(rx.is_disconnected());
|
||||
/// ```
|
||||
#[unstable(feature = "mpmc_channel", issue = "126840")]
|
||||
pub fn is_disconnected(&self) -> bool {
|
||||
match &self.flavor {
|
||||
ReceiverFlavor::Array(chan) => chan.is_disconnected(),
|
||||
ReceiverFlavor::List(chan) => chan.is_disconnected(),
|
||||
ReceiverFlavor::Zero(chan) => chan.is_disconnected(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "mpmc_channel", issue = "126840")]
|
||||
|
||||
@@ -316,4 +316,10 @@ pub(crate) fn is_empty(&self) -> bool {
|
||||
pub(crate) fn is_full(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Returns `true` if the channel is disconnected.
|
||||
pub(crate) fn is_disconnected(&self) -> bool {
|
||||
let inner = self.inner.lock().unwrap();
|
||||
inner.is_disconnected
|
||||
}
|
||||
}
|
||||
|
||||
@@ -607,6 +607,29 @@ impl<T> Sender<T> {
|
||||
pub fn send(&self, t: T) -> Result<(), SendError<T>> {
|
||||
self.inner.send(t)
|
||||
}
|
||||
|
||||
/// Returns `true` if the channel is disconnected.
|
||||
///
|
||||
/// Note that a return value of `false` does not guarantee the channel will
|
||||
/// remain connected. The channel may be disconnected immediately after this method
|
||||
/// returns, so a subsequent [`Sender::send`] may still fail with [`SendError`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(mpsc_is_disconnected)]
|
||||
///
|
||||
/// use std::sync::mpsc::channel;
|
||||
///
|
||||
/// let (tx, rx) = channel::<i32>();
|
||||
/// assert!(!tx.is_disconnected());
|
||||
/// drop(rx);
|
||||
/// assert!(tx.is_disconnected());
|
||||
/// ```
|
||||
#[unstable(feature = "mpsc_is_disconnected", issue = "153668")]
|
||||
pub fn is_disconnected(&self) -> bool {
|
||||
self.inner.is_disconnected()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@@ -1038,6 +1061,29 @@ pub fn iter(&self) -> Iter<'_, T> {
|
||||
pub fn try_iter(&self) -> TryIter<'_, T> {
|
||||
TryIter { rx: self }
|
||||
}
|
||||
|
||||
/// Returns `true` if the channel is disconnected.
|
||||
///
|
||||
/// Note that a return value of `false` does not guarantee the channel will
|
||||
/// remain connected. The channel may be disconnected immediately after this method
|
||||
/// returns, so a subsequent [`Receiver::recv`] may still fail with [`RecvError`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(mpsc_is_disconnected)]
|
||||
///
|
||||
/// use std::sync::mpsc::channel;
|
||||
///
|
||||
/// let (tx, rx) = channel::<i32>();
|
||||
/// assert!(!rx.is_disconnected());
|
||||
/// drop(tx);
|
||||
/// assert!(rx.is_disconnected());
|
||||
/// ```
|
||||
#[unstable(feature = "mpsc_is_disconnected", issue = "153668")]
|
||||
pub fn is_disconnected(&self) -> bool {
|
||||
self.inner.is_disconnected()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
@@ -634,7 +634,7 @@ pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "vxworks",
|
||||
all(target_os = "vxworks", vxworks_lt_25_09),
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
target_os = "rtems",
|
||||
@@ -643,7 +643,12 @@ pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
SystemTime::new(self.stat.st_mtime as i64, 0)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "horizon", target_os = "hurd", target_os = "nuttx"))]
|
||||
#[cfg(any(
|
||||
target_os = "horizon",
|
||||
target_os = "hurd",
|
||||
target_os = "nuttx",
|
||||
all(target_os = "vxworks", not(vxworks_lt_25_09))
|
||||
))]
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
SystemTime::new(self.stat.st_mtim.tv_sec as i64, self.stat.st_mtim.tv_nsec as i64)
|
||||
}
|
||||
@@ -669,7 +674,7 @@ pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "vxworks",
|
||||
all(target_os = "vxworks", vxworks_lt_25_09),
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
target_os = "rtems"
|
||||
@@ -678,7 +683,12 @@ pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
SystemTime::new(self.stat.st_atime as i64, 0)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "horizon", target_os = "hurd", target_os = "nuttx"))]
|
||||
#[cfg(any(
|
||||
target_os = "horizon",
|
||||
target_os = "hurd",
|
||||
target_os = "nuttx",
|
||||
all(target_os = "vxworks", not(vxworks_lt_25_09))
|
||||
))]
|
||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
SystemTime::new(self.stat.st_atim.tv_sec as i64, self.stat.st_atim.tv_nsec as i64)
|
||||
}
|
||||
|
||||
@@ -5,14 +5,17 @@
|
||||
//! allows setting up things that cannot be simply captured inside the bootstrap.toml, in addition to
|
||||
//! leading people away from manually editing most of the bootstrap.toml values.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::env::consts::EXE_SUFFIX;
|
||||
use std::fmt::Write as _;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::{MAIN_SEPARATOR_STR, Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use std::sync::LazyLock;
|
||||
use std::{fmt, fs, io};
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use sha2::Digest;
|
||||
|
||||
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
|
||||
@@ -529,7 +532,8 @@ fn install_git_hook_maybe(builder: &Builder<'_>, config: &Config) -> io::Result<
|
||||
}
|
||||
|
||||
/// Handles editor-specific setup differences
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
enum EditorKind {
|
||||
Emacs,
|
||||
Helix,
|
||||
@@ -538,6 +542,13 @@ enum EditorKind {
|
||||
Zed,
|
||||
}
|
||||
|
||||
static PARSED_HASHES: LazyLock<BTreeMap<EditorKind, Vec<&'static str>>> = LazyLock::new(|| {
|
||||
const ALL_HASHES: &str = include_str!("setup/hashes.json");
|
||||
let mut map: BTreeMap<_, Vec<_>> = serde_json::from_str(ALL_HASHES).unwrap();
|
||||
map.insert(EditorKind::Vim, map.get(&EditorKind::VsCode).unwrap().clone());
|
||||
map
|
||||
});
|
||||
|
||||
impl EditorKind {
|
||||
// Used in `./tests.rs`.
|
||||
#[cfg(test)]
|
||||
@@ -588,59 +599,7 @@ fn prompt_user() -> io::Result<Option<EditorKind>> {
|
||||
/// New entries should be appended whenever this is updated so we can detect
|
||||
/// outdated vs. user-modified settings files.
|
||||
fn hashes(&self) -> &'static [&'static str] {
|
||||
match self {
|
||||
EditorKind::Emacs => &[
|
||||
"51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0",
|
||||
"d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45",
|
||||
"b5dd299b93dca3ceeb9b335f929293cb3d4bf4977866fbe7ceeac2a8a9f99088",
|
||||
"631c837b0e98ae35fd48b0e5f743b1ca60adadf2d0a2b23566ba25df372cf1a9",
|
||||
"080955765db84bb6cbf178879f489c4e2369397626a6ecb3debedb94a9d0b3ce",
|
||||
"f501475c6654187091c924ae26187fa5791d74d4a8ab3fb61fbbe4c0275aade1",
|
||||
"54bc48fe1996177f5eef86d7231b33978e6d8b737cb0a899e622b7e975c95308",
|
||||
"08d30e455ceec6e01d9bcef8b9449f2ddd14d278ca8627cdad90e02d9f44e938",
|
||||
],
|
||||
EditorKind::Helix => &[
|
||||
"2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233",
|
||||
"6736d61409fbebba0933afd2e4c44ff2f97c1cb36cf0299a7f4a7819b8775040",
|
||||
"f252dcc30ca85a193a699581e5e929d5bd6c19d40d7a7ade5e257a9517a124a5",
|
||||
"198c195ed0c070d15907b279b8b4ea96198ca71b939f5376454f3d636ab54da5",
|
||||
"1c43ead340b20792b91d02b08494ee68708e7e09f56b6766629b4b72079208f1",
|
||||
"eec09a09452682060afd23dd5d3536ccac5615b3cdbf427366446901215fb9f6",
|
||||
"cb653043852d9d5ff4a5be56407b859ff9928be055ad3f307eb309aad04765e6",
|
||||
"e28b1930d16d3d8bbdeed7bd4a995613e648b49e08c9b6f5271880f520637fed",
|
||||
],
|
||||
EditorKind::Vim | EditorKind::VsCode => &[
|
||||
"ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8",
|
||||
"56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922",
|
||||
"af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0",
|
||||
"3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541",
|
||||
"47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923",
|
||||
"b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a",
|
||||
"828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000",
|
||||
"811fb3b063c739d261fd8590dd30242e117908f5a095d594fa04585daa18ec4d",
|
||||
"4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4",
|
||||
"c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d",
|
||||
"e53e9129ca5ee5dcbd6ec8b68c2d87376474eb154992deba3c6d9ab1703e0717",
|
||||
"f954316090936c7e590c253ca9d524008375882fa13c5b41d7e2547a896ff893",
|
||||
"701b73751efd7abd6487f2c79348dab698af7ac4427b79fa3d2087c867144b12",
|
||||
"a61df796c0c007cb6512127330564e49e57d558dec715703916a928b072a1054",
|
||||
"02a49ac2d31f00ef6e4531c44e00dac51cea895112e480553f1ba060b3942a47",
|
||||
"0aa4748848de0d1cb7ece92a0123c8897fef6de2f58aff8fda1426f098b7a798",
|
||||
"e5e357862e5d6d0d9da335e9823c07b8a7dc42bbf18d72cc5206ad1049cd8fcc",
|
||||
"a68fd5828e75f3e921f265e29ce1e9efa554083c3773fdb4b8e1ab3b2d9dc6cd",
|
||||
],
|
||||
EditorKind::Zed => &[
|
||||
"bbce727c269d1bd0c98afef4d612eb4ce27aea3c3a8968c5f10b31affbc40b6c",
|
||||
"a5380cf5dd9328731aecc5dfb240d16dac46ed272126b9728006151ef42f5909",
|
||||
"2e96bf0d443852b12f016c8fc9840ab3d0a2b4fe0b0fb3a157e8d74d5e7e0e26",
|
||||
"4fadd4c87389a601a27db0d3d74a142fa3a2e656ae78982e934dbe24bee32ad6",
|
||||
"f0bb3d23ab1a49175ab0ef5c4071af95bb03d01d460776cdb716d91333443382",
|
||||
"5ef83292111d9a8bb63b6afc3abf42d0bc78fe24985f0d2e039e73258b5dab8f",
|
||||
"74420c13094b530a986b37c4f1d23cb58c0e8e2295f5858ded129fb1574e66f9",
|
||||
"2d3b592c089b2ad2c528686a1e371af49922edad1c59accd5d5f31612a441568",
|
||||
"0767a2398ccc253274b184adbb9e018ce931bd0ef45baad06dad19b652c52951",
|
||||
],
|
||||
}
|
||||
PARSED_HASHES.get(self).unwrap()
|
||||
}
|
||||
|
||||
fn settings_path(&self, config: &Config) -> PathBuf {
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"emacs": [
|
||||
"51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0",
|
||||
"d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45",
|
||||
"b5dd299b93dca3ceeb9b335f929293cb3d4bf4977866fbe7ceeac2a8a9f99088",
|
||||
"631c837b0e98ae35fd48b0e5f743b1ca60adadf2d0a2b23566ba25df372cf1a9",
|
||||
"080955765db84bb6cbf178879f489c4e2369397626a6ecb3debedb94a9d0b3ce",
|
||||
"f501475c6654187091c924ae26187fa5791d74d4a8ab3fb61fbbe4c0275aade1",
|
||||
"54bc48fe1996177f5eef86d7231b33978e6d8b737cb0a899e622b7e975c95308",
|
||||
"08d30e455ceec6e01d9bcef8b9449f2ddd14d278ca8627cdad90e02d9f44e938"
|
||||
],
|
||||
"helix": [
|
||||
"2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233",
|
||||
"6736d61409fbebba0933afd2e4c44ff2f97c1cb36cf0299a7f4a7819b8775040",
|
||||
"f252dcc30ca85a193a699581e5e929d5bd6c19d40d7a7ade5e257a9517a124a5",
|
||||
"198c195ed0c070d15907b279b8b4ea96198ca71b939f5376454f3d636ab54da5",
|
||||
"1c43ead340b20792b91d02b08494ee68708e7e09f56b6766629b4b72079208f1",
|
||||
"eec09a09452682060afd23dd5d3536ccac5615b3cdbf427366446901215fb9f6",
|
||||
"cb653043852d9d5ff4a5be56407b859ff9928be055ad3f307eb309aad04765e6",
|
||||
"e28b1930d16d3d8bbdeed7bd4a995613e648b49e08c9b6f5271880f520637fed"
|
||||
],
|
||||
"vim": [
|
||||
"ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8",
|
||||
"56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922",
|
||||
"af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0",
|
||||
"3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541",
|
||||
"47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923",
|
||||
"b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a",
|
||||
"828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000",
|
||||
"811fb3b063c739d261fd8590dd30242e117908f5a095d594fa04585daa18ec4d",
|
||||
"4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4",
|
||||
"c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d",
|
||||
"e53e9129ca5ee5dcbd6ec8b68c2d87376474eb154992deba3c6d9ab1703e0717",
|
||||
"f954316090936c7e590c253ca9d524008375882fa13c5b41d7e2547a896ff893",
|
||||
"701b73751efd7abd6487f2c79348dab698af7ac4427b79fa3d2087c867144b12",
|
||||
"a61df796c0c007cb6512127330564e49e57d558dec715703916a928b072a1054",
|
||||
"02a49ac2d31f00ef6e4531c44e00dac51cea895112e480553f1ba060b3942a47",
|
||||
"0aa4748848de0d1cb7ece92a0123c8897fef6de2f58aff8fda1426f098b7a798",
|
||||
"e5e357862e5d6d0d9da335e9823c07b8a7dc42bbf18d72cc5206ad1049cd8fcc",
|
||||
"a68fd5828e75f3e921f265e29ce1e9efa554083c3773fdb4b8e1ab3b2d9dc6cd"
|
||||
],
|
||||
"vscode": [
|
||||
"ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8",
|
||||
"56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922",
|
||||
"af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0",
|
||||
"3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541",
|
||||
"47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923",
|
||||
"b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a",
|
||||
"828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000",
|
||||
"811fb3b063c739d261fd8590dd30242e117908f5a095d594fa04585daa18ec4d",
|
||||
"4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4",
|
||||
"c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d",
|
||||
"e53e9129ca5ee5dcbd6ec8b68c2d87376474eb154992deba3c6d9ab1703e0717",
|
||||
"f954316090936c7e590c253ca9d524008375882fa13c5b41d7e2547a896ff893",
|
||||
"701b73751efd7abd6487f2c79348dab698af7ac4427b79fa3d2087c867144b12",
|
||||
"a61df796c0c007cb6512127330564e49e57d558dec715703916a928b072a1054",
|
||||
"02a49ac2d31f00ef6e4531c44e00dac51cea895112e480553f1ba060b3942a47",
|
||||
"0aa4748848de0d1cb7ece92a0123c8897fef6de2f58aff8fda1426f098b7a798",
|
||||
"e5e357862e5d6d0d9da335e9823c07b8a7dc42bbf18d72cc5206ad1049cd8fcc",
|
||||
"a68fd5828e75f3e921f265e29ce1e9efa554083c3773fdb4b8e1ab3b2d9dc6cd"
|
||||
],
|
||||
"zed": [
|
||||
"bbce727c269d1bd0c98afef4d612eb4ce27aea3c3a8968c5f10b31affbc40b6c",
|
||||
"a5380cf5dd9328731aecc5dfb240d16dac46ed272126b9728006151ef42f5909",
|
||||
"2e96bf0d443852b12f016c8fc9840ab3d0a2b4fe0b0fb3a157e8d74d5e7e0e26",
|
||||
"4fadd4c87389a601a27db0d3d74a142fa3a2e656ae78982e934dbe24bee32ad6",
|
||||
"f0bb3d23ab1a49175ab0ef5c4071af95bb03d01d460776cdb716d91333443382",
|
||||
"5ef83292111d9a8bb63b6afc3abf42d0bc78fe24985f0d2e039e73258b5dab8f",
|
||||
"74420c13094b530a986b37c4f1d23cb58c0e8e2295f5858ded129fb1574e66f9",
|
||||
"2d3b592c089b2ad2c528686a1e371af49922edad1c59accd5d5f31612a441568",
|
||||
"0767a2398ccc253274b184adbb9e018ce931bd0ef45baad06dad19b652c52951"
|
||||
]
|
||||
}
|
||||
@@ -1,3 +1,8 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
use sha2::Digest;
|
||||
|
||||
use super::EditorKind;
|
||||
@@ -5,16 +10,41 @@
|
||||
|
||||
#[test]
|
||||
fn check_matching_settings_hash() {
|
||||
// Needs to be a btree so we serialize in a deterministic order.
|
||||
let mut mismatched = BTreeMap::new();
|
||||
|
||||
for editor in EditorKind::ALL {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(&editor.settings_template());
|
||||
let hash = hex_encode(hasher.finalize().as_slice());
|
||||
assert_eq!(
|
||||
&hash,
|
||||
editor.hashes().last().unwrap(),
|
||||
"Update `EditorKind::hashes()` with the new hash of `{}` for `EditorKind::{:?}`",
|
||||
editor.settings_template(),
|
||||
editor,
|
||||
);
|
||||
let actual = hex_encode(hasher.finalize().as_slice());
|
||||
let expected = *editor.hashes().last().unwrap();
|
||||
|
||||
if expected != actual {
|
||||
mismatched.insert(editor, (expected, actual));
|
||||
}
|
||||
}
|
||||
|
||||
if mismatched.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if option_env!("INSTA_UPDATE").is_some_and(|s| s != "0") {
|
||||
let mut updated = super::PARSED_HASHES.clone();
|
||||
for (editor, (_, actual)) in &mismatched {
|
||||
*updated.get_mut(editor).unwrap().last_mut().unwrap() = actual;
|
||||
}
|
||||
let hash_path =
|
||||
Path::new(env!("CARGO_MANIFEST_DIR")).join("src/core/build_steps/setup/hashes.json");
|
||||
let mut hash_file = File::create(hash_path).unwrap();
|
||||
serde_json::to_writer_pretty(&mut hash_file, &updated).unwrap();
|
||||
hash_file.write_all(b"\n").unwrap();
|
||||
} else {
|
||||
for (editor, (expected, actual)) in &mismatched {
|
||||
eprintln!("recorded hash did not match actual hash: {expected} != {actual}");
|
||||
eprintln!(
|
||||
"Run `x test --bless -- hash`, or manually update `setup/hashes.json` with the new hash of `{actual}` for `EditorKind::{editor:?}`"
|
||||
);
|
||||
}
|
||||
panic!("mismatched hashes");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ impl SplitDebuginfo {
|
||||
pub fn default_for_platform(target: TargetSelection) -> Self {
|
||||
if target.contains("apple") {
|
||||
SplitDebuginfo::Unpacked
|
||||
} else if target.is_windows() {
|
||||
} else if target.is_msvc() {
|
||||
SplitDebuginfo::Packed
|
||||
} else {
|
||||
SplitDebuginfo::Off
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
FROM ubuntu:26.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
bzip2 \
|
||||
g++ \
|
||||
gcc-multilib \
|
||||
make \
|
||||
ninja-build \
|
||||
file \
|
||||
curl \
|
||||
ca-certificates \
|
||||
python3 \
|
||||
git \
|
||||
cmake \
|
||||
sudo \
|
||||
gdb \
|
||||
llvm-22-tools \
|
||||
llvm-22-dev \
|
||||
libedit-dev \
|
||||
libssl-dev \
|
||||
pkg-config \
|
||||
zlib1g-dev \
|
||||
xz-utils \
|
||||
nodejs \
|
||||
mingw-w64 \
|
||||
# libgccjit dependencies
|
||||
flex \
|
||||
libmpfr-dev \
|
||||
libgmp-dev \
|
||||
libmpc3 \
|
||||
libmpc-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install powershell (universal package) so we can test x.ps1 on Linux
|
||||
# FIXME: need a "universal" version that supports libicu74, but for now it still works to ignore that dep.
|
||||
RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \
|
||||
dpkg --ignore-depends=libicu72 -i powershell.deb && \
|
||||
rm -f powershell.deb
|
||||
|
||||
COPY scripts/sccache.sh /scripts/
|
||||
RUN sh /scripts/sccache.sh
|
||||
|
||||
# We are disabling CI LLVM since this builder is intentionally using a host
|
||||
# LLVM, rather than the typical src/llvm-project LLVM.
|
||||
ENV NO_DOWNLOAD_CI_LLVM 1
|
||||
ENV EXTERNAL_LLVM 1
|
||||
|
||||
# Using llvm-link-shared due to libffi issues -- see #34486
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--build=x86_64-unknown-linux-gnu \
|
||||
--llvm-root=/usr/lib/llvm-22 \
|
||||
--enable-llvm-link-shared \
|
||||
--set rust.randomize-layout=true \
|
||||
--set rust.thin-lto-import-instr-limit=10
|
||||
|
||||
COPY scripts/shared.sh /scripts/
|
||||
|
||||
COPY scripts/x86_64-gnu-llvm.sh /scripts/
|
||||
COPY scripts/x86_64-gnu-llvm2.sh /scripts/
|
||||
COPY scripts/x86_64-gnu-llvm3.sh /scripts/
|
||||
COPY scripts/stage_2_test_set1.sh /scripts/
|
||||
COPY scripts/stage_2_test_set2.sh /scripts/
|
||||
|
||||
ENV SCRIPT "Must specify DOCKER_SCRIPT for this image"
|
||||
@@ -406,6 +406,31 @@ auto:
|
||||
DOCKER_SCRIPT: x86_64-gnu-llvm3.sh
|
||||
<<: *job-linux-4c
|
||||
|
||||
# The x86_64-gnu-llvm-22 job is split into multiple jobs to run tests in parallel.
|
||||
# x86_64-gnu-llvm-22-1 skips tests that run in x86_64-gnu-llvm-22-{2,3}.
|
||||
- name: x86_64-gnu-llvm-22-1
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
IMAGE: x86_64-gnu-llvm-22
|
||||
DOCKER_SCRIPT: stage_2_test_set2.sh
|
||||
<<: *job-linux-4c
|
||||
|
||||
# Skip tests that run in x86_64-gnu-llvm-22-{1,3}
|
||||
- name: x86_64-gnu-llvm-22-2
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
IMAGE: x86_64-gnu-llvm-22
|
||||
DOCKER_SCRIPT: x86_64-gnu-llvm2.sh
|
||||
<<: *job-linux-4c
|
||||
|
||||
# Skip tests that run in x86_64-gnu-llvm-22-{1,2}
|
||||
- name: x86_64-gnu-llvm-22-3
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
IMAGE: x86_64-gnu-llvm-22
|
||||
DOCKER_SCRIPT: x86_64-gnu-llvm3.sh
|
||||
<<: *job-linux-4c
|
||||
|
||||
- name: x86_64-gnu-nopt
|
||||
<<: *job-linux-4c
|
||||
|
||||
|
||||
@@ -28,6 +28,12 @@ Target triplets available:
|
||||
|
||||
The minimum supported version is VxWorks 7.
|
||||
|
||||
### Environment
|
||||
|
||||
#### `WIND_RELEASE_ID`
|
||||
|
||||
In VxWorks build environment, the environment variable `WIND_RELEASE_ID` indicates the VxWorks release version used for the build. The `WIND_RELEASE_ID` can be used to conditionally compile features/code or handle version specific behaviour.
|
||||
|
||||
## Building
|
||||
|
||||
Rust for each target can be cross-compiled with its specific target vsb configuration. Std support is added but not yet fully tested.
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
// This is part of series of regression tests for some diagnostics ICEs encountered in the wild with
|
||||
// suggestions having overlapping parts under https://github.com/rust-lang/rust/pull/146121.
|
||||
// This is one MCVE from the beta crater run regressions from issue 147973.
|
||||
|
||||
//@ needs-rustc-debug-assertions
|
||||
//@ known-bug: #147973
|
||||
|
||||
//@ aux-build: overlapping_spans_helper.rs
|
||||
extern crate overlapping_spans_helper;
|
||||
|
||||
fn main() {
|
||||
let _name = Some(1);
|
||||
overlapping_spans_helper::do_loop!(_name);
|
||||
}
|
||||
@@ -778,10 +778,6 @@ These tests revolve around the `--json` compiler flag. See [JSON Output](https:/
|
||||
|
||||
Tests exercising keywords, such as attempting to use them as identifiers when not contextual keywords.
|
||||
|
||||
## `tests/ui/kindck/`
|
||||
|
||||
**FIXME**: `kindck` is no longer a thing, these tests probably need to be audited and rehomed.
|
||||
|
||||
## `tests/ui/label/`
|
||||
|
||||
Exercises block and loop `'label`s.
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
//@ run-pass
|
||||
|
||||
#![allow(unused_must_use)]
|
||||
#![allow(dead_code)]
|
||||
use std::thread;
|
||||
|
||||
fn user(_i: isize) {}
|
||||
|
||||
fn foo() {
|
||||
// Here, i is *copied* into the proc (heap closure).
|
||||
// Requires allocation. The proc's copy is not mutable.
|
||||
let mut i = 0;
|
||||
let t = thread::spawn(move|| {
|
||||
user(i);
|
||||
println!("spawned {}", i)
|
||||
});
|
||||
i += 1;
|
||||
println!("original {}", i);
|
||||
t.join();
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
// Here, the original i has not been moved, only copied, so is still
|
||||
// mutable outside of the proc.
|
||||
let mut i = 0;
|
||||
while i < 10 {
|
||||
let t = thread::spawn(move|| {
|
||||
user(i);
|
||||
});
|
||||
i += 1;
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
fn car() {
|
||||
// Here, i must be shadowed in the proc to be mutable.
|
||||
let mut i = 0;
|
||||
while i < 10 {
|
||||
let t = thread::spawn(move|| {
|
||||
let mut i = i;
|
||||
i += 1;
|
||||
user(i);
|
||||
});
|
||||
i += 1;
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
@@ -17,10 +17,10 @@ note: required by a bound in `foo`
|
||||
|
|
||||
LL | fn foo<T: Foo>(_: [u8; T::N]) -> T {
|
||||
| ^^^ required by this bound in `foo`
|
||||
help: consider giving this pattern a type
|
||||
help: consider giving this pattern a type, where the type for type parameter `T` is specified
|
||||
|
|
||||
LL | let _: /* Type */ = foo([0; 1]);
|
||||
| ++++++++++++
|
||||
LL | let _: u8 = foo([0; 1]);
|
||||
| ++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
//! Regression test for https://github.com/rust-lang/rust/issues/153198
|
||||
#![feature(min_generic_const_args)]
|
||||
#![allow(incomplete_features, rust_2021_compatibility)]
|
||||
|
||||
trait Trait<T> {}
|
||||
|
||||
impl dyn Trait<{_}> {} //~ ERROR: the placeholder `_` is not allowed within types on item signatures
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,9 @@
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations
|
||||
--> $DIR/braced-const-infer.rs:7:17
|
||||
|
|
||||
LL | impl dyn Trait<{_}> {}
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0121`.
|
||||
@@ -0,0 +1,21 @@
|
||||
//! This test ensures compilation failure when trying to pass literals
|
||||
//! without explicitly stated type as inference variables in generic arguments.
|
||||
//!
|
||||
//! See https://github.com/rust-lang/rust/pull/153557
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(adt_const_params, min_generic_const_args, generic_const_parameter_types)]
|
||||
|
||||
fn main() {
|
||||
foo::<_, { 2 }>();
|
||||
//~^ ERROR: type annotations needed for the literal
|
||||
let _: PC<_, { 42 }> = PC { a: 1, b: 1 };
|
||||
//~^ ERROR: type annotations needed for the literal
|
||||
}
|
||||
|
||||
struct PC<T, const N: T> {
|
||||
//~^ ERROR: `T` can't be used as a const parameter type [E0741]
|
||||
a: T,
|
||||
}
|
||||
|
||||
fn foo<const N: usize, const A: [u8; N]>() {}
|
||||
@@ -0,0 +1,21 @@
|
||||
error[E0741]: `T` can't be used as a const parameter type
|
||||
--> $DIR/infer-vars-in-const-args-conflicting.rs:16:23
|
||||
|
|
||||
LL | struct PC<T, const N: T> {
|
||||
| ^
|
||||
|
||||
error: type annotations needed for the literal
|
||||
--> $DIR/infer-vars-in-const-args-conflicting.rs:10:16
|
||||
|
|
||||
LL | foo::<_, { 2 }>();
|
||||
| ^
|
||||
|
||||
error: type annotations needed for the literal
|
||||
--> $DIR/infer-vars-in-const-args-conflicting.rs:12:20
|
||||
|
|
||||
LL | let _: PC<_, { 42 }> = PC { a: 1, b: 1 };
|
||||
| ^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0741`.
|
||||
@@ -0,0 +1,22 @@
|
||||
//! This test ensures no errors are emitted when lowering literals with
|
||||
//! explicitly stated types and inference variables in the type of the const
|
||||
//! generic parameter.
|
||||
//!
|
||||
//! See https://github.com/rust-lang/rust/pull/153557
|
||||
|
||||
//@check-pass
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(adt_const_params,
|
||||
min_generic_const_args,
|
||||
generic_const_parameter_types,
|
||||
unsized_const_params
|
||||
)]
|
||||
|
||||
use std::marker::ConstParamTy_;
|
||||
|
||||
fn main() {
|
||||
foo::<_, 2_i32>();
|
||||
}
|
||||
|
||||
fn foo<T: ConstParamTy_, const N: T>() {}
|
||||
@@ -0,0 +1,20 @@
|
||||
//! Regression test for https://github.com/rust-lang/rust/issues/153198
|
||||
#![feature(min_generic_const_args)]
|
||||
#![allow(incomplete_features)]
|
||||
macro_rules! y {
|
||||
( $($matcher:tt)*) => {
|
||||
_ //~ ERROR: the placeholder `_` is not allowed within types on item signatures
|
||||
};
|
||||
}
|
||||
|
||||
struct A<T>; //~ ERROR: type parameter `T` is never used
|
||||
|
||||
const y: A<
|
||||
{
|
||||
y! {
|
||||
x
|
||||
}
|
||||
},
|
||||
> = 1; //~ ERROR: mismatched types
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,44 @@
|
||||
error[E0392]: type parameter `T` is never used
|
||||
--> $DIR/macro-const-arg-infer.rs:10:10
|
||||
|
|
||||
LL | struct A<T>;
|
||||
| ^ unused type parameter
|
||||
|
|
||||
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
|
||||
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/macro-const-arg-infer.rs:18:5
|
||||
|
|
||||
LL | const y: A<
|
||||
| __________-
|
||||
LL | | {
|
||||
LL | | y! {
|
||||
LL | | x
|
||||
LL | | }
|
||||
LL | | },
|
||||
LL | | > = 1;
|
||||
| | - ^ expected `A<_>`, found integer
|
||||
| |_|
|
||||
| expected because of the type of the constant
|
||||
|
|
||||
= note: expected struct `A<_>`
|
||||
found type `{integer}`
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/macro-const-arg-infer.rs:6:9
|
||||
|
|
||||
LL | _
|
||||
| ^ not allowed in type signatures
|
||||
...
|
||||
LL | / y! {
|
||||
LL | | x
|
||||
LL | | }
|
||||
| |_________- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0121, E0308, E0392.
|
||||
For more information about an error, try `rustc --explain E0121`.
|
||||
@@ -7,15 +7,17 @@
|
||||
// Don't break whenever Symbol numbering changes
|
||||
//@ normalize-stdout: "\d+#" -> "0#"
|
||||
|
||||
#![feature /* 0#0 */(decl_macro)]
|
||||
#![feature /* 0#0 */(no_core)]
|
||||
#![feature /* 0#0 */(decl_macro /* 0#0 */)]
|
||||
#![feature /* 0#0 */(no_core /* 0#0 */)]
|
||||
#![no_core /* 0#0 */]
|
||||
|
||||
macro lifetime_hygiene
|
||||
/*
|
||||
0#0
|
||||
*/ {
|
||||
($f:ident<$a:lifetime>) => { fn $f<$a, 'a>() {} }
|
||||
($f /* 0#0 */:ident /* 0#0 */<$a /* 0#0 */:lifetime /* 0#0 */>)
|
||||
=>
|
||||
{ fn /* 0#0 */ $f /* 0#0 */<$a /* 0#0 */, 'a /* 0#0 */>() {} }
|
||||
}
|
||||
fn f /* 0#0 */<'a /* 0#0 */, 'a /* 0#1 */>() {}
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
//@ check-pass
|
||||
//@ compile-flags: -Zunpretty=expanded,hygiene
|
||||
|
||||
// Regression test for token hygiene annotations in -Zunpretty=expanded,hygiene
|
||||
// Previously, metavar parameters in macro-generated macro_rules! definitions
|
||||
// were missing hygiene annotations, making identical `$marg` bindings
|
||||
// indistinguishable.
|
||||
|
||||
// Don't break whenever Symbol numbering changes
|
||||
//@ normalize-stdout: "\d+#" -> "0#"
|
||||
|
||||
#![feature(no_core)]
|
||||
#![no_core]
|
||||
|
||||
macro_rules! make_macro {
|
||||
(@inner $name:ident ($dol:tt) $a:ident) => {
|
||||
macro_rules! $name {
|
||||
($dol $a : expr, $dol marg : expr) => {}
|
||||
}
|
||||
};
|
||||
($name:ident) => {
|
||||
make_macro!{@inner $name ($) marg}
|
||||
};
|
||||
}
|
||||
|
||||
make_macro!(add2);
|
||||
@@ -0,0 +1,53 @@
|
||||
//@ check-pass
|
||||
//@ compile-flags: -Zunpretty=expanded,hygiene
|
||||
|
||||
// Regression test for token hygiene annotations in -Zunpretty=expanded,hygiene
|
||||
// Previously, metavar parameters in macro-generated macro_rules! definitions
|
||||
// were missing hygiene annotations, making identical `$marg` bindings
|
||||
// indistinguishable.
|
||||
|
||||
// Don't break whenever Symbol numbering changes
|
||||
//@ normalize-stdout: "\d+#" -> "0#"
|
||||
|
||||
#![feature /* 0#0 */(no_core /* 0#0 */)]
|
||||
#![no_core /* 0#0 */]
|
||||
|
||||
macro_rules! make_macro
|
||||
/*
|
||||
0#0
|
||||
*/ {
|
||||
(@inner /* 0#0 */ $name /* 0#0 */:ident /* 0#0
|
||||
*/($dol /* 0#0 */:tt /* 0#0 */) $a /* 0#0 */:ident /* 0#0 */)
|
||||
=>
|
||||
{
|
||||
macro_rules /* 0#0 */! $name /* 0#0 */
|
||||
{
|
||||
($dol /* 0#0 */ $a /* 0#0 */ : expr /* 0#0 */, $dol /*
|
||||
0#0 */ marg /* 0#0 */ : expr /* 0#0 */) => {}
|
||||
}
|
||||
}; ($name /* 0#0 */:ident /* 0#0 */) =>
|
||||
{
|
||||
make_macro /* 0#0
|
||||
*/!{@inner /* 0#0 */ $name /* 0#0 */($) marg /* 0#0 */}
|
||||
};
|
||||
}
|
||||
macro_rules! add2
|
||||
/*
|
||||
0#0
|
||||
*/ {
|
||||
($ marg /* 0#1 */ : expr /* 0#2 */, $marg /* 0#2 */ : expr /*
|
||||
0#2 */) => {}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Expansions:
|
||||
crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
|
||||
crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "make_macro")
|
||||
crate0::{{expn2}}: parent: crate0::{{expn1}}, call_site_ctxt: #1, def_site_ctxt: #0, kind: Macro(Bang, "make_macro")
|
||||
|
||||
SyntaxContexts:
|
||||
#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
|
||||
#1: parent: #0, outer_mark: (crate0::{{expn1}}, SemiOpaque)
|
||||
#2: parent: #0, outer_mark: (crate0::{{expn2}}, SemiOpaque)
|
||||
*/
|
||||
@@ -0,0 +1,20 @@
|
||||
//@ check-pass
|
||||
//@ compile-flags: -Zunpretty=expanded,hygiene
|
||||
|
||||
// Regression test for token hygiene annotations in -Zunpretty=expanded,hygiene
|
||||
// Previously, tokens in macro_rules! bodies were missing hygiene annotations,
|
||||
// making it impossible to see how a macro's reference to a shadowed variable
|
||||
// is distinguished from the shadowing binding.
|
||||
|
||||
// Don't break whenever Symbol numbering changes
|
||||
//@ normalize-stdout: "\d+#" -> "0#"
|
||||
|
||||
#![feature(no_core)]
|
||||
#![no_core]
|
||||
|
||||
fn f() {
|
||||
let x = 0;
|
||||
macro_rules! use_x { () => { x }; }
|
||||
let x = 1;
|
||||
use_x!();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
//@ check-pass
|
||||
//@ compile-flags: -Zunpretty=expanded,hygiene
|
||||
|
||||
// Regression test for token hygiene annotations in -Zunpretty=expanded,hygiene
|
||||
// Previously, tokens in macro_rules! bodies were missing hygiene annotations,
|
||||
// making it impossible to see how a macro's reference to a shadowed variable
|
||||
// is distinguished from the shadowing binding.
|
||||
|
||||
// Don't break whenever Symbol numbering changes
|
||||
//@ normalize-stdout: "\d+#" -> "0#"
|
||||
|
||||
#![feature /* 0#0 */(no_core /* 0#0 */)]
|
||||
#![no_core /* 0#0 */]
|
||||
|
||||
fn f /* 0#0 */() {
|
||||
let x /* 0#0 */ = 0;
|
||||
macro_rules! use_x /* 0#0 */ { () => { x /* 0#0 */ }; }
|
||||
let x /* 0#0 */ = 1;
|
||||
x /* 0#1 */;
|
||||
}
|
||||
|
||||
/*
|
||||
Expansions:
|
||||
crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
|
||||
crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "use_x")
|
||||
|
||||
SyntaxContexts:
|
||||
#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
|
||||
#1: parent: #0, outer_mark: (crate0::{{expn1}}, SemiOpaque)
|
||||
*/
|
||||
@@ -5,10 +5,16 @@
|
||||
//@ normalize-stdout: "\d+#" -> "0#"
|
||||
|
||||
// minimal junk
|
||||
#![feature /* 0#0 */(no_core)]
|
||||
#![feature /* 0#0 */(no_core /* 0#0 */)]
|
||||
#![no_core /* 0#0 */]
|
||||
|
||||
macro_rules! foo /* 0#0 */ { ($x: ident) => { y + $x } }
|
||||
macro_rules! foo
|
||||
/*
|
||||
0#0
|
||||
*/ {
|
||||
($x /* 0#0 */: ident /* 0#0 */) =>
|
||||
{ y /* 0#0 */ + $x /* 0#0 */ }
|
||||
}
|
||||
|
||||
fn bar /* 0#0 */() {
|
||||
let x /* 0#0 */ = 1;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
//@ run-rustfix
|
||||
fn main() {
|
||||
let v = vec![1, 2];
|
||||
let sum: i32 = v //~ ERROR: type annotations needed
|
||||
.iter()
|
||||
.map(|val| *val)
|
||||
.sum(); // `sum::<T>` needs `T` to be specified
|
||||
// In this case any integer would fit, but we resolve to `i32` because that's what `{integer}`
|
||||
// got coerced to. If the user needs further hinting that they can change the integer type, that
|
||||
// can come from other suggestions. (#100802)
|
||||
let bool = sum > 0;
|
||||
assert_eq!(bool, true);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
//@ run-rustfix
|
||||
fn main() {
|
||||
let v = vec![1, 2];
|
||||
let sum = v //~ ERROR: type annotations needed
|
||||
.iter()
|
||||
.map(|val| *val)
|
||||
.sum(); // `sum::<T>` needs `T` to be specified
|
||||
// In this case any integer would fit, but we resolve to `i32` because that's what `{integer}`
|
||||
// got coerced to. If the user needs further hinting that they can change the integer type, that
|
||||
// can come from other suggestions. (#100802)
|
||||
let bool = sum > 0;
|
||||
assert_eq!(bool, true);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
error[E0283]: type annotations needed
|
||||
--> $DIR/cannot-infer-iterator-sum-return-type.rs:4:9
|
||||
|
|
||||
LL | let sum = v
|
||||
| ^^^
|
||||
...
|
||||
LL | .sum(); // `sum::<T>` needs `T` to be specified
|
||||
| --- type must be known at this point
|
||||
|
|
||||
= note: the type must implement `Sum<i32>`
|
||||
help: the trait `Sum` is implemented for `i32`
|
||||
--> $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
|
||||
::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
|
||||
|
|
||||
= note: in this macro invocation
|
||||
note: required by a bound in `std::iter::Iterator::sum`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
= note: this error originates in the macro `integer_sum_product` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: consider giving `sum` an explicit type, where the type for type parameter `S` is specified
|
||||
|
|
||||
LL | let sum: i32 = v
|
||||
| +++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
@@ -1,15 +0,0 @@
|
||||
trait Foo {
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<T:Copy> Foo for T {
|
||||
}
|
||||
|
||||
fn take_param<T:Foo>(foo: &T) { }
|
||||
|
||||
fn main() {
|
||||
let x: Box<_> = Box::new(3);
|
||||
take_param(&x);
|
||||
//~^ ERROR the trait bound `Box<{integer}>: Foo` is not satisfied
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
|
||||
--> $DIR/kindck-impl-type-params-2.rs:13:16
|
||||
|
|
||||
LL | take_param(&x);
|
||||
| ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required for `Box<{integer}>` to implement `Foo`
|
||||
--> $DIR/kindck-impl-type-params-2.rs:6:14
|
||||
|
|
||||
LL | impl<T:Copy> Foo for T {
|
||||
| ---- ^^^ ^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: required by a bound in `take_param`
|
||||
--> $DIR/kindck-impl-type-params-2.rs:9:17
|
||||
|
|
||||
LL | fn take_param<T:Foo>(foo: &T) { }
|
||||
| ^^^ required by this bound in `take_param`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
@@ -1,56 +0,0 @@
|
||||
error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:21:16
|
||||
|
|
||||
LL | take_param(&x);
|
||||
| ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required for `Box<{integer}>` to implement `Foo`
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:14:14
|
||||
|
|
||||
LL | impl<T:Copy> Foo for T {
|
||||
| ---- ^^^ ^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: required by a bound in `take_param`
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:17:17
|
||||
|
|
||||
LL | fn take_param<T:Foo>(foo: &T) { }
|
||||
| ^^^ required by this bound in `take_param`
|
||||
|
||||
error[E0038]: the trait `Foo` is not dyn compatible
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:28:19
|
||||
|
|
||||
LL | let z = &x as &dyn Foo;
|
||||
| ^^^^^^^^ `Foo` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:10:13
|
||||
|
|
||||
LL | trait Foo : Copy {
|
||||
| --- ^^^^ ...because it requires `Self: Sized`
|
||||
| |
|
||||
| this trait is not dyn compatible...
|
||||
|
||||
error[E0038]: the trait `Foo` is not dyn compatible
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:28:13
|
||||
|
|
||||
LL | let z = &x as &dyn Foo;
|
||||
| ^^ `Foo` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:10:13
|
||||
|
|
||||
LL | trait Foo : Copy {
|
||||
| --- ^^^^ ...because it requires `Self: Sized`
|
||||
| |
|
||||
| this trait is not dyn compatible...
|
||||
= note: required for the cast from `&Box<{integer}>` to `&dyn Foo`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0038, E0277.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
||||
@@ -1,25 +0,0 @@
|
||||
error[E0277]: `Rc<usize>` cannot be sent between threads safely
|
||||
--> $DIR/kindck-nonsendable-1.rs:9:9
|
||||
|
|
||||
LL | bar(move|| foo(x));
|
||||
| --- ------^^^^^^^
|
||||
| | |
|
||||
| | `Rc<usize>` cannot be sent between threads safely
|
||||
| | within this `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}`
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: within `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}`, the trait `Send` is not implemented for `Rc<usize>`
|
||||
note: required because it's used within this closure
|
||||
--> $DIR/kindck-nonsendable-1.rs:9:9
|
||||
|
|
||||
LL | bar(move|| foo(x));
|
||||
| ^^^^^^
|
||||
note: required by a bound in `bar`
|
||||
--> $DIR/kindck-nonsendable-1.rs:5:21
|
||||
|
|
||||
LL | fn bar<F:FnOnce() + Send>(_: F) { }
|
||||
| ^^^^ required by this bound in `bar`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
@@ -1,26 +0,0 @@
|
||||
// Test which of the builtin types are considered sendable. The tests
|
||||
// in this file all test the "kind" violates detected during kindck.
|
||||
// See all `regions-bounded-by-send.rs`
|
||||
|
||||
fn assert_send<T:Send>() { }
|
||||
trait Dummy { }
|
||||
trait Message : Send { }
|
||||
|
||||
// careful with object types, who knows what they close over...
|
||||
|
||||
fn object_ref_with_static_bound_not_ok() {
|
||||
assert_send::<&'static (dyn Dummy + 'static)>();
|
||||
//~^ ERROR `&'static (dyn Dummy + 'static)` cannot be sent between threads safely [E0277]
|
||||
}
|
||||
|
||||
fn box_object_with_no_bound_not_ok<'a>() {
|
||||
assert_send::<Box<dyn Dummy>>();
|
||||
//~^ ERROR `dyn Dummy` cannot be sent between threads safely
|
||||
}
|
||||
|
||||
fn object_with_send_bound_ok() {
|
||||
assert_send::<&'static (dyn Dummy + Sync)>();
|
||||
assert_send::<Box<dyn Dummy + Send>>();
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -1,33 +0,0 @@
|
||||
error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
|
||||
--> $DIR/kindck-send-object.rs:12:19
|
||||
|
|
||||
LL | assert_send::<&'static (dyn Dummy + 'static)>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`
|
||||
= note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/kindck-send-object.rs:5:18
|
||||
|
|
||||
LL | fn assert_send<T:Send>() { }
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error[E0277]: `dyn Dummy` cannot be sent between threads safely
|
||||
--> $DIR/kindck-send-object.rs:17:19
|
||||
|
|
||||
LL | assert_send::<Box<dyn Dummy>>();
|
||||
| ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `Send` is not implemented for `dyn Dummy`
|
||||
= note: required for `std::ptr::Unique<dyn Dummy>` to implement `Send`
|
||||
note: required because it appears within the type `Box<dyn Dummy>`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/kindck-send-object.rs:5:18
|
||||
|
|
||||
LL | fn assert_send<T:Send>() { }
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
@@ -1,33 +0,0 @@
|
||||
// Test which object types are considered sendable. This test
|
||||
// is broken into two parts because some errors occur in distinct
|
||||
// phases in the compiler. See kindck-send-object2.rs as well!
|
||||
|
||||
fn assert_send<T:Send+'static>() { }
|
||||
trait Dummy { }
|
||||
|
||||
// careful with object types, who knows what they close over...
|
||||
fn test51<'a>() {
|
||||
assert_send::<&'a dyn Dummy>();
|
||||
//~^ ERROR `&'a (dyn Dummy + 'a)` cannot be sent between threads safely [E0277]
|
||||
}
|
||||
fn test52<'a>() {
|
||||
assert_send::<&'a (dyn Dummy + Sync)>();
|
||||
//~^ ERROR: lifetime may not live long enough
|
||||
}
|
||||
|
||||
// ...unless they are properly bounded
|
||||
fn test60() {
|
||||
assert_send::<&'static (dyn Dummy + Sync)>();
|
||||
}
|
||||
fn test61() {
|
||||
assert_send::<Box<dyn Dummy + Send>>();
|
||||
}
|
||||
|
||||
// closure and object types can have lifetime bounds which make
|
||||
// them not ok
|
||||
fn test_71<'a>() {
|
||||
assert_send::<Box<dyn Dummy + 'a>>();
|
||||
//~^ ERROR `(dyn Dummy + 'a)` cannot be sent between threads safely
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -1,41 +0,0 @@
|
||||
error[E0277]: `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
|
||||
--> $DIR/kindck-send-object1.rs:10:19
|
||||
|
|
||||
LL | assert_send::<&'a dyn Dummy>();
|
||||
| ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`
|
||||
= note: required for `&'a (dyn Dummy + 'a)` to implement `Send`
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/kindck-send-object1.rs:5:18
|
||||
|
|
||||
LL | fn assert_send<T:Send+'static>() { }
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely
|
||||
--> $DIR/kindck-send-object1.rs:29:19
|
||||
|
|
||||
LL | assert_send::<Box<dyn Dummy + 'a>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `Send` is not implemented for `(dyn Dummy + 'a)`
|
||||
= note: required for `std::ptr::Unique<(dyn Dummy + 'a)>` to implement `Send`
|
||||
note: required because it appears within the type `Box<(dyn Dummy + 'a)>`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/kindck-send-object1.rs:5:18
|
||||
|
|
||||
LL | fn assert_send<T:Send+'static>() { }
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/kindck-send-object1.rs:14:5
|
||||
|
|
||||
LL | fn test52<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | assert_send::<&'a (dyn Dummy + Sync)>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
@@ -1,24 +0,0 @@
|
||||
// Continue kindck-send-object1.rs.
|
||||
|
||||
fn assert_send<T:Send>() { }
|
||||
trait Dummy { }
|
||||
|
||||
fn test50() {
|
||||
assert_send::<&'static dyn Dummy>();
|
||||
//~^ ERROR `&'static (dyn Dummy + 'static)` cannot be sent between threads safely [E0277]
|
||||
}
|
||||
|
||||
fn test53() {
|
||||
assert_send::<Box<dyn Dummy>>();
|
||||
//~^ ERROR `dyn Dummy` cannot be sent between threads safely
|
||||
}
|
||||
|
||||
// ...unless they are properly bounded
|
||||
fn test60() {
|
||||
assert_send::<&'static (dyn Dummy + Sync)>();
|
||||
}
|
||||
fn test61() {
|
||||
assert_send::<Box<dyn Dummy + Send>>();
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -1,33 +0,0 @@
|
||||
error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
|
||||
--> $DIR/kindck-send-object2.rs:7:19
|
||||
|
|
||||
LL | assert_send::<&'static dyn Dummy>();
|
||||
| ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`
|
||||
= note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/kindck-send-object2.rs:3:18
|
||||
|
|
||||
LL | fn assert_send<T:Send>() { }
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error[E0277]: `dyn Dummy` cannot be sent between threads safely
|
||||
--> $DIR/kindck-send-object2.rs:12:19
|
||||
|
|
||||
LL | assert_send::<Box<dyn Dummy>>();
|
||||
| ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `Send` is not implemented for `dyn Dummy`
|
||||
= note: required for `std::ptr::Unique<dyn Dummy>` to implement `Send`
|
||||
note: required because it appears within the type `Box<dyn Dummy>`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/kindck-send-object2.rs:3:18
|
||||
|
|
||||
LL | fn assert_send<T:Send>() { }
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
@@ -1,16 +0,0 @@
|
||||
// Test which of the builtin types are considered sendable.
|
||||
|
||||
fn assert_send<T:Send>() { }
|
||||
|
||||
// owned content are ok
|
||||
fn test30() { assert_send::<Box<isize>>(); }
|
||||
fn test31() { assert_send::<String>(); }
|
||||
fn test32() { assert_send::<Vec<isize> >(); }
|
||||
|
||||
// but not if they own a bad thing
|
||||
fn test40() {
|
||||
assert_send::<Box<*mut u8>>();
|
||||
//~^ ERROR `*mut u8` cannot be sent between threads safely
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -1,19 +0,0 @@
|
||||
error[E0277]: `*mut u8` cannot be sent between threads safely
|
||||
--> $DIR/kindck-send-owned.rs:12:19
|
||||
|
|
||||
LL | assert_send::<Box<*mut u8>>();
|
||||
| ^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `Send` is not implemented for `*mut u8`
|
||||
= note: required for `std::ptr::Unique<*mut u8>` to implement `Send`
|
||||
note: required because it appears within the type `Box<*mut u8>`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/kindck-send-owned.rs:3:18
|
||||
|
|
||||
LL | fn assert_send<T:Send>() { }
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
@@ -1,15 +0,0 @@
|
||||
extern crate core;
|
||||
|
||||
fn assert_send<T: Send>() {}
|
||||
|
||||
fn test70() {
|
||||
assert_send::<*mut isize>();
|
||||
//~^ ERROR `*mut isize` cannot be sent between threads safely
|
||||
}
|
||||
|
||||
fn test71<'a>() {
|
||||
assert_send::<*mut &'a isize>();
|
||||
//~^ ERROR `*mut &'a isize` cannot be sent between threads safely
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -1,29 +0,0 @@
|
||||
error[E0277]: `*mut isize` cannot be sent between threads safely
|
||||
--> $DIR/kindck-send-unsafe.rs:6:19
|
||||
|
|
||||
LL | assert_send::<*mut isize>();
|
||||
| ^^^^^^^^^^ `*mut isize` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `Send` is not implemented for `*mut isize`
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/kindck-send-unsafe.rs:3:19
|
||||
|
|
||||
LL | fn assert_send<T: Send>() {}
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error[E0277]: `*mut &'a isize` cannot be sent between threads safely
|
||||
--> $DIR/kindck-send-unsafe.rs:11:19
|
||||
|
|
||||
LL | assert_send::<*mut &'a isize>();
|
||||
| ^^^^^^^^^^^^^^ `*mut &'a isize` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `Send` is not implemented for `*mut &'a isize`
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/kindck-send-unsafe.rs:3:19
|
||||
|
|
||||
LL | fn assert_send<T: Send>() {}
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
@@ -0,0 +1,13 @@
|
||||
#[macro_export]
|
||||
macro_rules! identity {
|
||||
($x:ident) => {
|
||||
$x
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! do_loop {
|
||||
($x:ident) => {
|
||||
for $crate::identity!($x) in $x {}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
//@ check-pass
|
||||
//@ aux-build:external-macro-issue-148114.rs
|
||||
|
||||
// This test ensures we do not trigger the lint on external macros
|
||||
// ref. <https://github.com/rust-lang/rust/issues/148114>
|
||||
|
||||
#![deny(for_loops_over_fallibles)]
|
||||
|
||||
extern crate external_macro_issue_148114 as dep;
|
||||
|
||||
fn main() {
|
||||
let _name = Some(1);
|
||||
dep::do_loop!(_name);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// This test ensures that the `for-loops-over-fallibles` lint doesn't suggest
|
||||
// removing `next`.
|
||||
// ref. <https://github.com/rust-lang/rust-clippy/issues/16133>
|
||||
|
||||
#![forbid(for_loops_over_fallibles)]
|
||||
//~^ NOTE: the lint level is defined here
|
||||
|
||||
fn main() {
|
||||
macro_rules! mac {
|
||||
(next $e:expr) => {
|
||||
$e.iter().next()
|
||||
};
|
||||
}
|
||||
|
||||
for _ in mac!(next [1, 2]) {}
|
||||
//~^ ERROR: for loop over an `Option`. This is more readably written as an `if let` statement
|
||||
//~| NOTE: in this expansion of desugaring of `for` loop
|
||||
//~| NOTE: in this expansion of desugaring of `for` loop
|
||||
//~| HELP: to check pattern in a loop use `while let`
|
||||
//~| HELP: consider using `if let` to clear intent
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
error: for loop over an `Option`. This is more readably written as an `if let` statement
|
||||
--> $DIR/macro-iterator-next.rs:15:14
|
||||
|
|
||||
LL | for _ in mac!(next [1, 2]) {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/macro-iterator-next.rs:5:11
|
||||
|
|
||||
LL | #![forbid(for_loops_over_fallibles)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: to check pattern in a loop use `while let`
|
||||
|
|
||||
LL - for _ in mac!(next [1, 2]) {}
|
||||
LL + while let Some(_) = mac!(next [1, 2]) {}
|
||||
|
|
||||
help: consider using `if let` to clear intent
|
||||
|
|
||||
LL - for _ in mac!(next [1, 2]) {}
|
||||
LL + if let Some(_) = mac!(next [1, 2]) {}
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
use std::ptr;
|
||||
|
||||
fn main() { //~ NOTE: this implicit `()` return type influences the call expression's return type
|
||||
let a = 0;
|
||||
ptr::read(&a)
|
||||
//~^ ERROR: mismatched types
|
||||
//~| NOTE: expected `*const ()`, found `&{integer}`
|
||||
//~| NOTE: arguments to this function are incorrect
|
||||
//~| NOTE: expected raw pointer
|
||||
//~| NOTE: function defined here
|
||||
}
|
||||
|
||||
fn foo() { //~ NOTE: this implicit `()` return type influences the call expression's return type
|
||||
let a = 0;
|
||||
return ptr::read(&a);
|
||||
//~^ ERROR: mismatched types
|
||||
//~| NOTE: expected `*const ()`, found `&{integer}`
|
||||
//~| NOTE: arguments to this function are incorrect
|
||||
//~| NOTE: expected raw pointer
|
||||
//~| NOTE: function defined here
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expectation-from-return-type.rs:5:15
|
||||
|
|
||||
LL | fn main() {
|
||||
| - this implicit `()` return type influences the call expression's return type
|
||||
LL | let a = 0;
|
||||
LL | ptr::read(&a)
|
||||
| --------- ^^ expected `*const ()`, found `&{integer}`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected raw pointer `*const ()`
|
||||
found reference `&{integer}`
|
||||
note: function defined here
|
||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expectation-from-return-type.rs:15:22
|
||||
|
|
||||
LL | fn foo() {
|
||||
| - this implicit `()` return type influences the call expression's return type
|
||||
LL | let a = 0;
|
||||
LL | return ptr::read(&a);
|
||||
| --------- ^^ expected `*const ()`, found `&{integer}`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected raw pointer `*const ()`
|
||||
found reference `&{integer}`
|
||||
note: function defined here
|
||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
@@ -16,6 +16,8 @@ LL | arg.map(|v| &**v)
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/transforming-option-ref-issue-127545.rs:9:19
|
||||
|
|
||||
LL | pub fn bar(arg: Option<&Vec<i32>>) -> &[i32] {
|
||||
| ------ this return type influences the call expression's return type
|
||||
LL | arg.unwrap_or(&[])
|
||||
| --------- ^^^ expected `&Vec<i32>`, found `&[_; 0]`
|
||||
| |
|
||||
@@ -41,6 +43,8 @@ LL + arg.map_or(&[], |v| v)
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/transforming-option-ref-issue-127545.rs:13:19
|
||||
|
|
||||
LL | pub fn barzz<'a>(arg: Option<&'a Vec<i32>>, v: &'a [i32]) -> &'a [i32] {
|
||||
| --------- this return type influences the call expression's return type
|
||||
LL | arg.unwrap_or(v)
|
||||
| --------- ^ expected `&Vec<i32>`, found `&[i32]`
|
||||
| |
|
||||
@@ -66,6 +70,8 @@ LL + arg.map_or(v, |v| v)
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/transforming-option-ref-issue-127545.rs:17:19
|
||||
|
|
||||
LL | pub fn convert_result(arg: Result<&Vec<i32>, ()>) -> &[i32] {
|
||||
| ------ this return type influences the call expression's return type
|
||||
LL | arg.unwrap_or(&[])
|
||||
| --------- ^^^ expected `&Vec<i32>`, found `&[_; 0]`
|
||||
| |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4)
|
||||
Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:26:37: 26:43 (#3) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:26:43: 26:44 (#3) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:26:44: 26:45 (#3) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:26:45: 26:50 (#3) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:26:50: 26:51 (#3) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:26:51: 26:53 (#3) }]
|
||||
Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }]
|
||||
#![feature /* 0#0 */(prelude_import)]
|
||||
#![feature /* 0#0 */(prelude_import /* 0#0 */)]
|
||||
//@ aux-build:make-macro.rs
|
||||
//@ proc-macro: meta-macro.rs
|
||||
//@ edition:2018
|
||||
@@ -30,7 +30,8 @@ macro_rules! produce_it
|
||||
*/ {
|
||||
() =>
|
||||
{
|
||||
meta_macro::print_def_site!($crate::dummy!());
|
||||
meta_macro /* 0#0 */::print_def_site /* 0#0
|
||||
*/!($crate /* 0#0 */::dummy /* 0#0 */!());
|
||||
// `print_def_site!` will respan the `$crate` identifier
|
||||
// with `Span::def_site()`. This should cause it to resolve
|
||||
// relative to `meta_macro`, *not* `make_macro` (despite
|
||||
|
||||
@@ -20,7 +20,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
|
||||
span: $DIR/nonterminal-token-hygiene.rs:23:27: 23:32 (#4),
|
||||
},
|
||||
]
|
||||
#![feature /* 0#0 */(prelude_import)]
|
||||
#![feature /* 0#0 */(prelude_import /* 0#0 */)]
|
||||
#![no_std /* 0#0 */]
|
||||
// Make sure that marks from declarative macros are applied to tokens in nonterminal.
|
||||
|
||||
@@ -34,7 +34,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
|
||||
//@ proc-macro: test-macros.rs
|
||||
//@ edition: 2015
|
||||
|
||||
#![feature /* 0#0 */(decl_macro)]
|
||||
#![feature /* 0#0 */(decl_macro /* 0#0 */)]
|
||||
#![no_std /* 0#0 */]
|
||||
extern crate core /* 0#2 */;
|
||||
#[prelude_import /* 0#1 */]
|
||||
@@ -49,15 +49,22 @@ macro_rules! outer
|
||||
/*
|
||||
0#0
|
||||
*/ {
|
||||
($item:item) =>
|
||||
($item /* 0#0 */:item /* 0#0 */) =>
|
||||
{
|
||||
macro inner() { print_bang! { $item } } inner!();
|
||||
macro /* 0#0 */ inner /* 0#0 */()
|
||||
{ print_bang /* 0#0 */! { $item /* 0#0 */ } } inner /* 0#0
|
||||
*/!();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
struct S /* 0#0 */;
|
||||
macro inner /* 0#3 */ { () => { print_bang! { struct S; } } }
|
||||
macro inner
|
||||
/*
|
||||
0#3
|
||||
*/ {
|
||||
() => { print_bang /* 0#3 */! { struct /* 0#0 */ S /* 0#0 */; } }
|
||||
}
|
||||
|
||||
struct S /* 0#5 */;
|
||||
// OK, not a duplicate definition of `S`
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
|
||||
// arguments (like `'a`) outlive `'b`.
|
||||
//
|
||||
// Rule OutlivesNominalType from RFC 1214.
|
||||
|
||||
//@ check-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
mod rev_variant_struct_region {
|
||||
struct Foo<'a> {
|
||||
x: fn(&'a i32),
|
||||
}
|
||||
enum Bar<'a,'b> {
|
||||
V(&'a Foo<'b>)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -1,20 +0,0 @@
|
||||
// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
|
||||
// arguments (like `'a`) outlive `'b`.
|
||||
//
|
||||
// Rule OutlivesNominalType from RFC 1214.
|
||||
|
||||
//@ check-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
mod variant_struct_region {
|
||||
struct Foo<'a> {
|
||||
x: &'a i32,
|
||||
}
|
||||
enum Bar<'a,'b> {
|
||||
V(&'a Foo<'b>)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -1,20 +0,0 @@
|
||||
// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
|
||||
// arguments (like `'a`) outlive `'b`.
|
||||
//
|
||||
// Rule OutlivesNominalType from RFC 1214.
|
||||
|
||||
//@ check-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
mod variant_struct_type {
|
||||
struct Foo<T> {
|
||||
x: fn(T)
|
||||
}
|
||||
enum Bar<'a,'b> {
|
||||
V(&'a Foo<&'b i32>)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -1,20 +0,0 @@
|
||||
// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
|
||||
// arguments (like `'a`) outlive `'b`.
|
||||
//
|
||||
// Rule OutlivesNominalType from RFC 1214.
|
||||
|
||||
//@ check-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
mod variant_struct_type {
|
||||
struct Foo<T> {
|
||||
x: T
|
||||
}
|
||||
enum Bar<'a,'b> {
|
||||
V(&'a Foo<&'b i32>)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -1,20 +0,0 @@
|
||||
// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
|
||||
// arguments (like `'a`) outlive `'b`.
|
||||
//
|
||||
// Rule OutlivesNominalType from RFC 1214.
|
||||
|
||||
//@ check-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
mod rev_variant_struct_region {
|
||||
struct Foo<'a> {
|
||||
x: fn(&'a i32),
|
||||
}
|
||||
struct Bar<'a,'b> {
|
||||
f: &'a Foo<'b>
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -1,20 +0,0 @@
|
||||
// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
|
||||
// arguments (like `'a`) outlive `'b`.
|
||||
//
|
||||
// Rule OutlivesNominalType from RFC 1214.
|
||||
|
||||
//@ check-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
mod variant_struct_region {
|
||||
struct Foo<'a> {
|
||||
x: &'a i32,
|
||||
}
|
||||
struct Bar<'a,'b> {
|
||||
f: &'a Foo<'b>
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -1,20 +0,0 @@
|
||||
// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
|
||||
// arguments (like `'a`) outlive `'b`.
|
||||
//
|
||||
// Rule OutlivesNominalType from RFC 1214.
|
||||
|
||||
//@ check-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
mod rev_variant_struct_type {
|
||||
struct Foo<T> {
|
||||
x: fn(T)
|
||||
}
|
||||
struct Bar<'a,'b> {
|
||||
f: &'a Foo<&'b i32>
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -1,20 +0,0 @@
|
||||
// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
|
||||
// arguments (like `'a`) outlive `'b`.
|
||||
//
|
||||
// Rule OutlivesNominalType from RFC 1214.
|
||||
|
||||
//@ check-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
mod variant_struct_type {
|
||||
struct Foo<T> {
|
||||
x: T
|
||||
}
|
||||
struct Bar<'a,'b> {
|
||||
f: &'a Foo<&'b i32>
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -0,0 +1,80 @@
|
||||
// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
|
||||
// arguments (like `'a`) outlive `'b`.
|
||||
//
|
||||
// Rule OutlivesNominalType from RFC 1214.
|
||||
|
||||
//@ check-pass
|
||||
|
||||
mod variant_enum_region {
|
||||
struct Foo<'a> {
|
||||
x: &'a i32,
|
||||
}
|
||||
enum Bar<'a, 'b> {
|
||||
V(&'a Foo<'b>),
|
||||
}
|
||||
}
|
||||
|
||||
mod rev_variant_enum_region {
|
||||
struct Foo<'a> {
|
||||
x: fn(&'a i32),
|
||||
}
|
||||
enum Bar<'a, 'b> {
|
||||
V(&'a Foo<'b>),
|
||||
}
|
||||
}
|
||||
|
||||
mod variant_enum_type {
|
||||
struct Foo<T> {
|
||||
x: T,
|
||||
}
|
||||
enum Bar<'a, 'b> {
|
||||
V(&'a Foo<&'b i32>),
|
||||
}
|
||||
}
|
||||
|
||||
mod rev_variant_enum_type {
|
||||
struct Foo<T> {
|
||||
x: fn(T),
|
||||
}
|
||||
enum Bar<'a, 'b> {
|
||||
V(&'a Foo<&'b i32>),
|
||||
}
|
||||
}
|
||||
|
||||
mod variant_struct_region {
|
||||
struct Foo<'a> {
|
||||
x: &'a i32,
|
||||
}
|
||||
struct Bar<'a, 'b> {
|
||||
f: &'a Foo<'b>,
|
||||
}
|
||||
}
|
||||
|
||||
mod rev_variant_struct_region {
|
||||
struct Foo<'a> {
|
||||
x: fn(&'a i32),
|
||||
}
|
||||
struct Bar<'a, 'b> {
|
||||
f: &'a Foo<'b>,
|
||||
}
|
||||
}
|
||||
|
||||
mod variant_struct_type {
|
||||
struct Foo<T> {
|
||||
x: T,
|
||||
}
|
||||
struct Bar<'a, 'b> {
|
||||
f: &'a Foo<&'b i32>,
|
||||
}
|
||||
}
|
||||
|
||||
mod rev_variant_struct_type {
|
||||
struct Foo<T> {
|
||||
x: fn(T),
|
||||
}
|
||||
struct Bar<'a, 'b> {
|
||||
f: &'a Foo<&'b i32>,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
fn assert_copy<T:Copy>() { }
|
||||
fn assert_copy<T: Copy>() {}
|
||||
|
||||
trait Dummy { }
|
||||
trait Dummy {}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct MyStruct {
|
||||
@@ -16,8 +16,8 @@ struct MyNoncopyStruct {
|
||||
x: Box<char>,
|
||||
}
|
||||
|
||||
fn test<'a,T,U:Copy>(_: &'a isize) {
|
||||
// lifetime pointers are ok...
|
||||
fn test<'a, T, U: Copy>(_: &'a isize) {
|
||||
// references are ok...
|
||||
assert_copy::<&'static isize>();
|
||||
assert_copy::<&'a isize>();
|
||||
assert_copy::<&'a str>();
|
||||
@@ -25,25 +25,25 @@ fn test<'a,T,U:Copy>(_: &'a isize) {
|
||||
|
||||
// ...unless they are mutable
|
||||
assert_copy::<&'static mut isize>(); //~ ERROR : Copy` is not satisfied
|
||||
assert_copy::<&'a mut isize>(); //~ ERROR : Copy` is not satisfied
|
||||
assert_copy::<&'a mut isize>(); //~ ERROR : Copy` is not satisfied
|
||||
|
||||
// boxes are not ok
|
||||
assert_copy::<Box<isize>>(); //~ ERROR : Copy` is not satisfied
|
||||
assert_copy::<String>(); //~ ERROR : Copy` is not satisfied
|
||||
assert_copy::<Vec<isize> >(); //~ ERROR : Copy` is not satisfied
|
||||
assert_copy::<Box<isize>>(); //~ ERROR : Copy` is not satisfied
|
||||
assert_copy::<String>(); //~ ERROR : Copy` is not satisfied
|
||||
assert_copy::<Vec<isize>>(); //~ ERROR : Copy` is not satisfied
|
||||
assert_copy::<Box<&'a mut isize>>(); //~ ERROR : Copy` is not satisfied
|
||||
|
||||
// borrowed object types are generally ok
|
||||
// borrowed trait objects are generally ok
|
||||
assert_copy::<&'a dyn Dummy>();
|
||||
assert_copy::<&'a (dyn Dummy + Send)>();
|
||||
assert_copy::<&'static (dyn Dummy + Send)>();
|
||||
|
||||
// owned object types are not ok
|
||||
// boxed trait objects are not ok
|
||||
assert_copy::<Box<dyn Dummy>>(); //~ ERROR : Copy` is not satisfied
|
||||
assert_copy::<Box<dyn Dummy + Send>>(); //~ ERROR : Copy` is not satisfied
|
||||
|
||||
// mutable object types are not ok
|
||||
assert_copy::<&'a mut (dyn Dummy + Send)>(); //~ ERROR : Copy` is not satisfied
|
||||
// mutable references to trait objects are not ok
|
||||
assert_copy::<&'a mut (dyn Dummy + Send)>(); //~ ERROR : Copy` is not satisfied
|
||||
|
||||
// raw ptrs are ok
|
||||
assert_copy::<*const isize>();
|
||||
@@ -55,7 +55,7 @@ fn test<'a,T,U:Copy>(_: &'a isize) {
|
||||
assert_copy::<()>();
|
||||
|
||||
// tuples are ok
|
||||
assert_copy::<(isize,isize)>();
|
||||
assert_copy::<(isize, isize)>();
|
||||
|
||||
// structs of POD are ok
|
||||
assert_copy::<MyStruct>();
|
||||
@@ -64,8 +64,7 @@ fn test<'a,T,U:Copy>(_: &'a isize) {
|
||||
assert_copy::<MyNoncopyStruct>(); //~ ERROR : Copy` is not satisfied
|
||||
|
||||
// ref counted types are not ok
|
||||
assert_copy::<Rc<isize>>(); //~ ERROR : Copy` is not satisfied
|
||||
assert_copy::<Rc<isize>>(); //~ ERROR : Copy` is not satisfied
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
}
|
||||
pub fn main() {}
|
||||
@@ -1,14 +1,14 @@
|
||||
error[E0277]: the trait bound `&'static mut isize: Copy` is not satisfied
|
||||
--> $DIR/kindck-copy.rs:27:19
|
||||
--> $DIR/basic-copyable-types.rs:27:19
|
||||
|
|
||||
LL | assert_copy::<&'static mut isize>();
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize`
|
||||
|
|
||||
note: required by a bound in `assert_copy`
|
||||
--> $DIR/kindck-copy.rs:5:18
|
||||
--> $DIR/basic-copyable-types.rs:5:19
|
||||
|
|
||||
LL | fn assert_copy<T:Copy>() { }
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
LL | fn assert_copy<T: Copy>() {}
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
help: consider removing the leading `&`-reference
|
||||
|
|
||||
LL - assert_copy::<&'static mut isize>();
|
||||
@@ -16,16 +16,16 @@ LL + assert_copy::<isize>();
|
||||
|
|
||||
|
||||
error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
|
||||
--> $DIR/kindck-copy.rs:28:19
|
||||
--> $DIR/basic-copyable-types.rs:28:19
|
||||
|
|
||||
LL | assert_copy::<&'a mut isize>();
|
||||
| ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize`
|
||||
|
|
||||
note: required by a bound in `assert_copy`
|
||||
--> $DIR/kindck-copy.rs:5:18
|
||||
--> $DIR/basic-copyable-types.rs:5:19
|
||||
|
|
||||
LL | fn assert_copy<T:Copy>() { }
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
LL | fn assert_copy<T: Copy>() {}
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
help: consider removing the leading `&`-reference
|
||||
|
|
||||
LL - assert_copy::<&'a mut isize>();
|
||||
@@ -33,117 +33,117 @@ LL + assert_copy::<isize>();
|
||||
|
|
||||
|
||||
error[E0277]: the trait bound `Box<isize>: Copy` is not satisfied
|
||||
--> $DIR/kindck-copy.rs:31:19
|
||||
--> $DIR/basic-copyable-types.rs:31:19
|
||||
|
|
||||
LL | assert_copy::<Box<isize>>();
|
||||
| ^^^^^^^^^^ the trait `Copy` is not implemented for `Box<isize>`
|
||||
|
|
||||
note: required by a bound in `assert_copy`
|
||||
--> $DIR/kindck-copy.rs:5:18
|
||||
--> $DIR/basic-copyable-types.rs:5:19
|
||||
|
|
||||
LL | fn assert_copy<T:Copy>() { }
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
LL | fn assert_copy<T: Copy>() {}
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
|
||||
error[E0277]: the trait bound `String: Copy` is not satisfied
|
||||
--> $DIR/kindck-copy.rs:32:19
|
||||
--> $DIR/basic-copyable-types.rs:32:19
|
||||
|
|
||||
LL | assert_copy::<String>();
|
||||
| ^^^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
|
||||
note: required by a bound in `assert_copy`
|
||||
--> $DIR/kindck-copy.rs:5:18
|
||||
--> $DIR/basic-copyable-types.rs:5:19
|
||||
|
|
||||
LL | fn assert_copy<T:Copy>() { }
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
LL | fn assert_copy<T: Copy>() {}
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
|
||||
error[E0277]: the trait bound `Vec<isize>: Copy` is not satisfied
|
||||
--> $DIR/kindck-copy.rs:33:19
|
||||
--> $DIR/basic-copyable-types.rs:33:19
|
||||
|
|
||||
LL | assert_copy::<Vec<isize> >();
|
||||
LL | assert_copy::<Vec<isize>>();
|
||||
| ^^^^^^^^^^ the trait `Copy` is not implemented for `Vec<isize>`
|
||||
|
|
||||
note: required by a bound in `assert_copy`
|
||||
--> $DIR/kindck-copy.rs:5:18
|
||||
--> $DIR/basic-copyable-types.rs:5:19
|
||||
|
|
||||
LL | fn assert_copy<T:Copy>() { }
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
LL | fn assert_copy<T: Copy>() {}
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
|
||||
error[E0277]: the trait bound `Box<&'a mut isize>: Copy` is not satisfied
|
||||
--> $DIR/kindck-copy.rs:34:19
|
||||
--> $DIR/basic-copyable-types.rs:34:19
|
||||
|
|
||||
LL | assert_copy::<Box<&'a mut isize>>();
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<&'a mut isize>`
|
||||
|
|
||||
note: required by a bound in `assert_copy`
|
||||
--> $DIR/kindck-copy.rs:5:18
|
||||
--> $DIR/basic-copyable-types.rs:5:19
|
||||
|
|
||||
LL | fn assert_copy<T:Copy>() { }
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
LL | fn assert_copy<T: Copy>() {}
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
|
||||
error[E0277]: the trait bound `Box<dyn Dummy>: Copy` is not satisfied
|
||||
--> $DIR/kindck-copy.rs:42:19
|
||||
--> $DIR/basic-copyable-types.rs:42:19
|
||||
|
|
||||
LL | assert_copy::<Box<dyn Dummy>>();
|
||||
| ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<dyn Dummy>`
|
||||
|
|
||||
note: required by a bound in `assert_copy`
|
||||
--> $DIR/kindck-copy.rs:5:18
|
||||
--> $DIR/basic-copyable-types.rs:5:19
|
||||
|
|
||||
LL | fn assert_copy<T:Copy>() { }
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
LL | fn assert_copy<T: Copy>() {}
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
|
||||
error[E0277]: the trait bound `Box<dyn Dummy + Send>: Copy` is not satisfied
|
||||
--> $DIR/kindck-copy.rs:43:19
|
||||
--> $DIR/basic-copyable-types.rs:43:19
|
||||
|
|
||||
LL | assert_copy::<Box<dyn Dummy + Send>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<dyn Dummy + Send>`
|
||||
|
|
||||
note: required by a bound in `assert_copy`
|
||||
--> $DIR/kindck-copy.rs:5:18
|
||||
--> $DIR/basic-copyable-types.rs:5:19
|
||||
|
|
||||
LL | fn assert_copy<T:Copy>() { }
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
LL | fn assert_copy<T: Copy>() {}
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
|
||||
error[E0277]: the trait bound `&'a mut (dyn Dummy + Send + 'a): Copy` is not satisfied
|
||||
--> $DIR/kindck-copy.rs:46:19
|
||||
--> $DIR/basic-copyable-types.rs:46:19
|
||||
|
|
||||
LL | assert_copy::<&'a mut (dyn Dummy + Send)>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut (dyn Dummy + Send + 'a)`
|
||||
|
|
||||
note: required by a bound in `assert_copy`
|
||||
--> $DIR/kindck-copy.rs:5:18
|
||||
--> $DIR/basic-copyable-types.rs:5:19
|
||||
|
|
||||
LL | fn assert_copy<T:Copy>() { }
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
LL | fn assert_copy<T: Copy>() {}
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
|
||||
error[E0277]: the trait bound `MyNoncopyStruct: Copy` is not satisfied
|
||||
--> $DIR/kindck-copy.rs:64:19
|
||||
--> $DIR/basic-copyable-types.rs:64:19
|
||||
|
|
||||
LL | assert_copy::<MyNoncopyStruct>();
|
||||
| ^^^^^^^^^^^^^^^ unsatisfied trait bound
|
||||
|
|
||||
help: the trait `Copy` is not implemented for `MyNoncopyStruct`
|
||||
--> $DIR/kindck-copy.rs:15:1
|
||||
--> $DIR/basic-copyable-types.rs:15:1
|
||||
|
|
||||
LL | struct MyNoncopyStruct {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `assert_copy`
|
||||
--> $DIR/kindck-copy.rs:5:18
|
||||
--> $DIR/basic-copyable-types.rs:5:19
|
||||
|
|
||||
LL | fn assert_copy<T:Copy>() { }
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
LL | fn assert_copy<T: Copy>() {}
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
|
||||
error[E0277]: the trait bound `Rc<isize>: Copy` is not satisfied
|
||||
--> $DIR/kindck-copy.rs:67:19
|
||||
--> $DIR/basic-copyable-types.rs:67:19
|
||||
|
|
||||
LL | assert_copy::<Rc<isize>>();
|
||||
| ^^^^^^^^^ the trait `Copy` is not implemented for `Rc<isize>`
|
||||
|
|
||||
note: required by a bound in `assert_copy`
|
||||
--> $DIR/kindck-copy.rs:5:18
|
||||
--> $DIR/basic-copyable-types.rs:5:19
|
||||
|
|
||||
LL | fn assert_copy<T:Copy>() { }
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
LL | fn assert_copy<T: Copy>() {}
|
||||
| ^^^^ required by this bound in `assert_copy`
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user