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:
bors
2026-03-19 18:03:58 +00:00
109 changed files with 1834 additions and 1150 deletions
+4 -3
View File
@@ -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
+7 -3
View File
@@ -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()
}
+7 -10
View File
@@ -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 {
+1 -1
View File
@@ -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,
+136 -128
View File
@@ -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) -> ! {
+4 -1
View File
@@ -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));
}
+12 -10
View File
@@ -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)
+2 -1
View File
@@ -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),
}
+1
View File
@@ -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")]
+1
View File
@@ -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)]
+9 -1
View File
@@ -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
+3 -3
View File
@@ -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
+2 -3
View File
@@ -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);
+87 -7
View File
@@ -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 -3
View File
@@ -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 -3
View File
@@ -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] =
+2 -2
View File
@@ -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;
}
+3
View File
@@ -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)
}
}
+1
View File
@@ -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)]
+50 -46
View File
@@ -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)]
+24
View File
@@ -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))
}
+30
View File
@@ -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
}
+54
View File
@@ -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")]
+6
View File
@@ -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
}
}
+46
View File
@@ -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")]
+14 -4
View File
@@ -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)
}
+13 -54
View File
@@ -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"
+25
View File
@@ -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.
-14
View File
@@ -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);
}
-4
View File
@@ -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)
*/
+20
View File
@@ -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)
*/
+8 -2
View File
@@ -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`.
-26
View File
@@ -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() { }
-33
View File
@@ -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`.
-33
View File
@@ -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`.
-24
View File
@@ -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`.
-16
View File
@@ -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() { }
-19
View File
@@ -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`.
-15
View File
@@ -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() {}
-29
View File
@@ -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