"rustc_index",
"rustc_infer",
"rustc_lexer",
+ "rustc_macros",
"rustc_middle",
"rustc_mir_dataflow",
"rustc_serialize",
[[package]]
name = "smallvec"
-version = "1.7.0"
+version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
+checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2"
[[package]]
name = "snap"
[dependencies]
bitflags = "1.2.1"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
edition = "2021"
[dependencies]
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_index = { path = "../rustc_index" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_macros = { path = "../rustc_macros" }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
bitflags = "1.2.1"
rustc_errors = { path = "../rustc_errors" }
rustc_session = { path = "../rustc_session" }
rustc_ast = { path = "../rustc_ast" }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
itertools = "0.10.1"
tracing = "0.1"
polonius-engine = "0.13.0"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_graphviz = { path = "../rustc_graphviz" }
rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
rustc_lexer = { path = "../rustc_lexer" }
+rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_const_eval = { path = "../rustc_const_eval" }
rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
use std::rc::Rc;
use crate::region_infer::values::RegionElement;
+use crate::session_diagnostics::HigherRankedErrorCause;
+use crate::session_diagnostics::HigherRankedLifetimeError;
+use crate::session_diagnostics::HigherRankedSubtypeError;
use crate::MirBorrowckCtxt;
#[derive(Clone)]
// up in the existing UI tests. Consider investigating this
// some more.
mbcx.buffer_error(
- mbcx.infcx.tcx.sess.struct_span_err(cause.span, "higher-ranked subtype error"),
+ mbcx.infcx.tcx.sess.create_err(HigherRankedSubtypeError { span: cause.span }),
);
}
}
tcx: TyCtxt<'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error");
- err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate));
- err
+ tcx.sess.create_err(HigherRankedLifetimeError {
+ cause: Some(HigherRankedErrorCause::CouldNotProve {
+ predicate: self.canonical_query.value.value.predicate.to_string(),
+ }),
+ span,
+ })
}
fn base_universe(&self) -> ty::UniverseIndex {
tcx: TyCtxt<'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error");
- err.note(&format!("could not normalize `{}`", self.canonical_query.value.value.value));
- err
+ tcx.sess.create_err(HigherRankedLifetimeError {
+ cause: Some(HigherRankedErrorCause::CouldNotNormalize {
+ value: self.canonical_query.value.value.value.to_string(),
+ }),
+ span,
+ })
}
fn base_universe(&self) -> ty::UniverseIndex {
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
// FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
// and is only the fallback when the nice error fails. Consider improving this some more.
- tcx.sess.struct_span_err(span, "higher-ranked lifetime error")
+ tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span })
}
fn base_universe(&self) -> ty::UniverseIndex {
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
// FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
// and is only the fallback when the nice error fails. Consider improving this some more.
- tcx.sess.struct_span_err(span, "higher-ranked lifetime error for opaque type!")
+ tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span })
}
fn base_universe(&self) -> ty::UniverseIndex {
use rustc_mir_dataflow::move_paths::{
IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
};
-use rustc_span::{sym, Span};
+use rustc_span::Span;
use crate::diagnostics::UseSpans;
use crate::prefixes::PrefixSet;
fn report(&mut self, error: GroupedMoveError<'tcx>) {
let (mut err, err_span) = {
- let (span, use_spans, original_path, kind, has_complex_bindings): (
- Span,
- Option<UseSpans<'tcx>>,
- Place<'tcx>,
- &IllegalMoveOriginKind<'_>,
- bool,
- ) = match error {
- GroupedMoveError::MovesFromPlace {
- span,
- original_path,
- ref kind,
- ref binds_to,
- ..
+ let (span, use_spans, original_path, kind) = match error {
+ GroupedMoveError::MovesFromPlace { span, original_path, ref kind, .. }
+ | GroupedMoveError::MovesFromValue { span, original_path, ref kind, .. } => {
+ (span, None, original_path, kind)
}
- | GroupedMoveError::MovesFromValue {
- span,
- original_path,
- ref kind,
- ref binds_to,
- ..
- } => (span, None, original_path, kind, !binds_to.is_empty()),
GroupedMoveError::OtherIllegalMove { use_spans, original_path, ref kind } => {
- (use_spans.args_or_use(), Some(use_spans), original_path, kind, false)
+ (use_spans.args_or_use(), Some(use_spans), original_path, kind)
}
};
debug!(
target_place,
span,
use_spans,
- has_complex_bindings,
),
&IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
self.cannot_move_out_of_interior_of_drop(span, ty)
deref_target_place: Place<'tcx>,
span: Span,
use_spans: Option<UseSpans<'tcx>>,
- has_complex_bindings: bool,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
// Inspect the type of the content behind the
// borrow to provide feedback about why this
}
}
};
- let ty = move_place.ty(self.body, self.infcx.tcx).ty;
- let def_id = match *ty.kind() {
- ty::Adt(self_def, _) => self_def.did(),
- ty::Foreign(def_id)
- | ty::FnDef(def_id, _)
- | ty::Closure(def_id, _)
- | ty::Generator(def_id, ..)
- | ty::Opaque(def_id, _) => def_id,
- _ => return err,
- };
- let diag_name = self.infcx.tcx.get_diagnostic_name(def_id);
- if matches!(diag_name, Some(sym::Option | sym::Result))
- && use_spans.map_or(true, |v| !v.for_closure())
- && !has_complex_bindings
- {
- err.span_suggestion_verbose(
- span.shrink_to_hi(),
- &format!("consider borrowing the `{}`'s content", diag_name.unwrap()),
- ".as_ref()",
- Applicability::MaybeIncorrect,
- );
- } else if let Some(use_spans) = use_spans {
+ if let Some(use_spans) = use_spans {
self.explain_captures(
&mut err, span, span, use_spans, move_place, None, "", "", "", false, true,
);
match self.local_names[local] {
Some(name) if !local_decl.from_compiler_desugaring() => {
- let label = match local_decl.local_info.as_ref().unwrap() {
- box LocalInfo::User(ClearCrossCrate::Set(
+ let label = match local_decl.local_info.as_deref().unwrap() {
+ LocalInfo::User(ClearCrossCrate::Set(
mir::BindingForm::ImplicitSelf(_),
)) => {
let (span, suggestion) =
Some((true, span, suggestion))
}
- box LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
+ LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
mir::VarBindingForm {
binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info,
// on for loops, RHS points to the iterator part
Some(DesugaringKind::ForLoop) => {
self.suggest_similar_mut_method_for_for_loop(&mut err);
- Some((
- false,
- opt_assignment_rhs_span.unwrap(),
- format!(
- "this iterator yields `{SIGIL}` {DESC}s",
- SIGIL = pointer_sigil,
- DESC = pointer_desc
- ),
- ))
+ err.span_label(opt_assignment_rhs_span.unwrap(), format!(
+ "this iterator yields `{pointer_sigil}` {pointer_desc}s",
+ ));
+ None
}
// don't create labels for compiler-generated spans
Some(_) => None,
None => {
- let (span, suggestion) = if name != kw::SelfLower {
+ let label = if name != kw::SelfLower {
suggest_ampmut(
self.infcx.tcx,
local_decl,
..
}),
))) => {
- suggest_ampmut_self(self.infcx.tcx, local_decl)
+ let (span, sugg) = suggest_ampmut_self(
+ self.infcx.tcx,
+ local_decl,
+ );
+ (true, span, sugg)
}
// explicit self (eg `self: &'a Self`)
_ => suggest_ampmut(
),
}
};
- Some((true, span, suggestion))
+ Some(label)
}
}
}
- box LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
+ LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
mir::VarBindingForm {
binding_mode: ty::BindingMode::BindByReference(_),
..
.map(|replacement| (true, pattern_span, replacement))
}
- box LocalInfo::User(ClearCrossCrate::Clear) => {
+ LocalInfo::User(ClearCrossCrate::Clear) => {
bug!("saw cleared local state")
}
}
}
Some((false, err_label_span, message)) => {
- err.span_label(err_label_span, &message);
+ err.span_label(
+ err_label_span,
+ &format!(
+ "consider changing this binding's type to be: `{message}`"
+ ),
+ );
}
None => {}
}
local_decl: &mir::LocalDecl<'tcx>,
opt_assignment_rhs_span: Option<Span>,
opt_ty_info: Option<Span>,
-) -> (Span, String) {
+) -> (bool, Span, String) {
if let Some(assignment_rhs_span) = opt_assignment_rhs_span
&& let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span)
{
let lt_name = &src[1..ws_pos];
let ty = src[ws_pos..].trim_start();
if !is_mutbl(ty) {
- return (assignment_rhs_span, format!("&{lt_name} mut {ty}"));
+ return (true, assignment_rhs_span, format!("&{lt_name} mut {ty}"));
}
} else if let Some(stripped) = src.strip_prefix('&') {
let stripped = stripped.trim_start();
if !is_mutbl(stripped) {
- return (assignment_rhs_span, format!("&mut {stripped}"));
+ return (true, assignment_rhs_span, format!("&mut {stripped}"));
}
}
}
- let highlight_span = match opt_ty_info {
+ let (suggestability, highlight_span) = match opt_ty_info {
// if this is a variable binding with an explicit type,
// try to highlight that for the suggestion.
- Some(ty_span) => ty_span,
+ Some(ty_span) => (true, ty_span),
// otherwise, just highlight the span associated with
// the (MIR) LocalDecl.
- None => local_decl.source_info.span,
+ None => (false, local_decl.source_info.span),
};
if let Ok(src) = tcx.sess.source_map().span_to_snippet(highlight_span)
{
let lt_name = &src[1..ws_pos];
let ty = &src[ws_pos..];
- return (highlight_span, format!("&{} mut{}", lt_name, ty));
+ return (true, highlight_span, format!("&{} mut{}", lt_name, ty));
}
let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
assert_eq!(ty_mut.mutbl, hir::Mutability::Not);
(
+ suggestability,
highlight_span,
if local_decl.ty.is_region_ptr() {
format!("&mut {}", ty_mut.ty)
use rustc_span::Span;
use crate::borrowck_errors;
+use crate::session_diagnostics::GenericDoesNotLiveLongEnough;
use super::{OutlivesSuggestionBuilder, RegionName};
use crate::region_infer::BlameConstraint;
// to report it; we could probably handle it by
// iterating over the universal regions and reporting
// an error that multiple bounds are required.
- self.buffer_error(self.infcx.tcx.sess.struct_span_err(
- type_test_span,
- &format!("`{}` does not live long enough", type_test.generic_kind),
+ self.buffer_error(self.infcx.tcx.sess.create_err(
+ GenericDoesNotLiveLongEnough {
+ kind: type_test.generic_kind.to_string(),
+ span: type_test_span,
+ },
));
}
}
mod prefixes;
mod region_infer;
mod renumber;
+mod session_diagnostics;
mod type_check;
mod universal_regions;
mod used_muts;
--- /dev/null
+use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_middle::ty::Ty;
+use rustc_span::Span;
+
+#[derive(SessionDiagnostic)]
+#[error(borrowck::move_unsized, code = "E0161")]
+pub(crate) struct MoveUnsized<'tcx> {
+ pub ty: Ty<'tcx>,
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(borrowck::higher_ranked_lifetime_error)]
+pub(crate) struct HigherRankedLifetimeError {
+ #[subdiagnostic]
+ pub cause: Option<HigherRankedErrorCause>,
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+pub(crate) enum HigherRankedErrorCause {
+ #[note(borrowck::could_not_prove)]
+ CouldNotProve { predicate: String },
+ #[note(borrowck::could_not_normalize)]
+ CouldNotNormalize { value: String },
+}
+
+#[derive(SessionDiagnostic)]
+#[error(borrowck::higher_ranked_subtype_error)]
+pub(crate) struct HigherRankedSubtypeError {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(borrowck::generic_does_not_live_long_enough)]
+pub(crate) struct GenericDoesNotLiveLongEnough {
+ pub kind: String,
+ #[primary_span]
+ pub span: Span,
+}
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::vec_map::VecMap;
-use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_mir_dataflow::move_paths::MoveData;
use rustc_mir_dataflow::ResultsCursor;
+use crate::session_diagnostics::MoveUnsized;
use crate::{
borrow_set::BorrowSet,
constraints::{OutlivesConstraint, OutlivesConstraintSet},
// slot or local, so to find all unsized rvalues it is enough
// to check all temps, return slots and locals.
if self.reported_errors.replace((ty, span)).is_none() {
- let mut diag = struct_span_err!(
- self.tcx().sess,
- span,
- E0161,
- "cannot move a value of type {0}: the size of {0} \
- cannot be statically determined",
- ty
- );
-
// While this is located in `nll::typeck` this error is not
// an NLL error, it's a required check to prevent creation
// of unsized rvalues in a call expression.
- diag.emit();
+ self.tcx().sess.emit_err(MoveUnsized { ty, span });
}
}
}
rustc_parse = { path = "../rustc_parse" }
rustc_target = { path = "../rustc_target" }
rustc_session = { path = "../rustc_session" }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_ast = { path = "../rustc_ast" }
rustc_expand = { path = "../rustc_expand" }
rustc_span = { path = "../rustc_span" }
[[package]]
name = "smallvec"
-version = "1.8.0"
+version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
+checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2"
[[package]]
name = "target-lexicon"
indexmap = "1.8.0"
libloading = { version = "0.6.0", optional = true }
once_cell = "1.10.0"
-smallvec = "1.6.1"
+smallvec = "1.8.1"
[patch.crates-io]
# Uncomment to use local checkout of cranelift
rustc_session = { path = "../rustc_session" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_target = { path = "../rustc_target" }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_ast = { path = "../rustc_ast" }
rustc_span = { path = "../rustc_span" }
pathdiff = "0.2.0"
serde_json = "1.0.59"
snap = "1"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
regex = "1.4"
rustc_serialize = { path = "../rustc_serialize" }
#![feature(associated_type_bounds)]
#![feature(strict_provenance)]
#![feature(int_roundings)]
+#![feature(if_let_guard)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
}
// This requires that atomic intrinsics follow a specific naming pattern:
- // "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
- name if name_str.starts_with("atomic_") => {
+ // "atomic_<operation>[_<ordering>]"
+ name if let Some(atomic) = name_str.strip_prefix("atomic_") => {
use crate::common::AtomicOrdering::*;
use crate::common::{AtomicRmwBinOp, SynchronizationScope};
- let split: Vec<_> = name_str.split('_').collect();
-
- let is_cxchg = split[1] == "cxchg" || split[1] == "cxchgweak";
- let (order, failorder) = match split.len() {
- 2 => (SequentiallyConsistent, SequentiallyConsistent),
- 3 => match split[2] {
- "unordered" => (Unordered, Unordered),
- "relaxed" => (Relaxed, Relaxed),
- "acq" => (Acquire, Acquire),
- "rel" => (Release, Relaxed),
- "acqrel" => (AcquireRelease, Acquire),
- "failrelaxed" if is_cxchg => (SequentiallyConsistent, Relaxed),
- "failacq" if is_cxchg => (SequentiallyConsistent, Acquire),
- _ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
- },
- 4 => match (split[2], split[3]) {
- ("acq", "failrelaxed") if is_cxchg => (Acquire, Relaxed),
- ("acqrel", "failrelaxed") if is_cxchg => (AcquireRelease, Relaxed),
- _ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
- },
- _ => bx.sess().fatal("Atomic intrinsic not in correct format"),
+ let Some((instruction, ordering)) = atomic.split_once('_') else {
+ bx.sess().fatal("Atomic intrinsic missing memory ordering");
+ };
+
+ let parse_ordering = |bx: &Bx, s| match s {
+ "unordered" => Unordered,
+ "relaxed" => Relaxed,
+ "acquire" => Acquire,
+ "release" => Release,
+ "acqrel" => AcquireRelease,
+ "seqcst" => SequentiallyConsistent,
+ _ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
};
let invalid_monomorphization = |ty| {
);
};
- match split[1] {
+ match instruction {
"cxchg" | "cxchgweak" => {
+ let Some((success, failure)) = ordering.split_once('_') else {
+ bx.sess().fatal("Atomic compare-exchange intrinsic missing failure memory ordering");
+ };
let ty = substs.type_at(0);
if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
- let weak = split[1] == "cxchgweak";
+ let weak = instruction == "cxchgweak";
let mut dst = args[0].immediate();
let mut cmp = args[1].immediate();
let mut src = args[2].immediate();
cmp = bx.ptrtoint(cmp, bx.type_isize());
src = bx.ptrtoint(src, bx.type_isize());
}
- let pair = bx.atomic_cmpxchg(dst, cmp, src, order, failorder, weak);
+ let pair = bx.atomic_cmpxchg(dst, cmp, src, parse_ordering(bx, success), parse_ordering(bx, failure), weak);
let val = bx.extract_value(pair, 0);
let success = bx.extract_value(pair, 1);
let val = bx.from_immediate(val);
let llty = bx.type_isize();
let ptr_llty = bx.type_ptr_to(llty);
source = bx.pointercast(source, ptr_llty);
- let result = bx.atomic_load(llty, source, order, size);
+ let result = bx.atomic_load(llty, source, parse_ordering(bx, ordering), size);
// ... and then cast the result back to a pointer
bx.inttoptr(result, bx.backend_type(layout))
} else {
- bx.atomic_load(bx.backend_type(layout), source, order, size)
+ bx.atomic_load(bx.backend_type(layout), source, parse_ordering(bx, ordering), size)
}
} else {
return invalid_monomorphization(ty);
ptr = bx.pointercast(ptr, ptr_llty);
val = bx.ptrtoint(val, bx.type_isize());
}
- bx.atomic_store(val, ptr, order, size);
+ bx.atomic_store(val, ptr, parse_ordering(bx, ordering), size);
return;
} else {
return invalid_monomorphization(ty);
}
"fence" => {
- bx.atomic_fence(order, SynchronizationScope::CrossThread);
+ bx.atomic_fence(parse_ordering(bx, ordering), SynchronizationScope::CrossThread);
return;
}
"singlethreadfence" => {
- bx.atomic_fence(order, SynchronizationScope::SingleThread);
+ bx.atomic_fence(parse_ordering(bx, ordering), SynchronizationScope::SingleThread);
return;
}
ptr = bx.pointercast(ptr, ptr_llty);
val = bx.ptrtoint(val, bx.type_isize());
}
- bx.atomic_rmw(atom_op, ptr, val, order)
+ bx.atomic_rmw(atom_op, ptr, val, parse_ordering(bx, ordering))
} else {
return invalid_monomorphization(ty);
}
'tcx: 'mir,
{
error.print_backtrace();
- let stacktrace = ecx.generate_stacktrace();
- ConstEvalErr {
- error: error.into_kind(),
- stacktrace,
- span: span.unwrap_or_else(|| ecx.cur_span()),
- }
+ let mut stacktrace = ecx.generate_stacktrace();
+ // Filter out `requires_caller_location` frames.
+ stacktrace.retain(|frame| !frame.instance.def.requires_caller_location(*ecx.tcx));
+ // If `span` is missing, use topmost remaining frame, or else the "root" span from `ecx.tcx`.
+ let span = span.or_else(|| stacktrace.first().map(|f| f.span)).unwrap_or(ecx.tcx.span);
+ ConstEvalErr { error: error.into_kind(), stacktrace, span }
}
pub fn struct_error(
}
};
- Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), &msg))
+ Err(err.report_as_error(ecx.tcx.at(err.span), &msg))
} else {
let hir_id = tcx.hir().local_def_id_to_hir_id(def.as_local().unwrap().did);
Err(err.report_as_lint(
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
-use rustc_target::abi::VariantIdx;
use crate::interpret::{
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MemPlaceMeta,
}
}
-/// Tries to destructure constants of type Array or Adt into the constants
-/// of its fields.
-pub(crate) fn try_destructure_const<'tcx>(
- tcx: TyCtxt<'tcx>,
- const_: ty::Const<'tcx>,
-) -> Option<ty::DestructuredConst<'tcx>> {
- if let ty::ConstKind::Value(valtree) = const_.kind() {
- let branches = match valtree {
- ty::ValTree::Branch(b) => b,
- _ => return None,
- };
-
- let (fields, variant) = match const_.ty().kind() {
- ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
- // construct the consts for the elements of the array/slice
- let field_consts = branches
- .iter()
- .map(|b| {
- tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Value(*b), ty: *inner_ty })
- })
- .collect::<Vec<_>>();
- debug!(?field_consts);
-
- (field_consts, None)
- }
- ty::Adt(def, _) if def.variants().is_empty() => bug!("unreachable"),
- ty::Adt(def, substs) => {
- let variant_idx = if def.is_enum() {
- VariantIdx::from_u32(branches[0].unwrap_leaf().try_to_u32().ok()?)
- } else {
- VariantIdx::from_u32(0)
- };
- let fields = &def.variant(variant_idx).fields;
- let mut field_consts = Vec::with_capacity(fields.len());
-
- // Note: First element inValTree corresponds to variant of enum
- let mut valtree_idx = if def.is_enum() { 1 } else { 0 };
- for field in fields {
- let field_ty = field.ty(tcx, substs);
- let field_valtree = branches[valtree_idx]; // first element of branches is variant
- let field_const = tcx.mk_const(ty::ConstS {
- kind: ty::ConstKind::Value(field_valtree),
- ty: field_ty,
- });
- field_consts.push(field_const);
- valtree_idx += 1;
- }
- debug!(?field_consts);
-
- (field_consts, Some(variant_idx))
- }
- ty::Tuple(elem_tys) => {
- let fields = elem_tys
- .iter()
- .enumerate()
- .map(|(i, elem_ty)| {
- let elem_valtree = branches[i];
- tcx.mk_const(ty::ConstS {
- kind: ty::ConstKind::Value(elem_valtree),
- ty: elem_ty,
- })
- })
- .collect::<Vec<_>>();
-
- (fields, None)
- }
- _ => bug!("cannot destructure constant {:?}", const_),
- };
-
- let fields = tcx.arena.alloc_from_iter(fields.into_iter());
-
- Some(ty::DestructuredConst { variant, fields })
- } else {
- None
- }
-}
-
#[instrument(skip(tcx), level = "debug")]
pub(crate) fn try_destructure_mir_constant<'tcx>(
tcx: TyCtxt<'tcx>,
}
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
assert_eq!(def_a, def_b);
- if def_a.is_box() || def_b.is_box() {
- if !def_a.is_box() || !def_b.is_box() {
- span_bug!(
- self.cur_span(),
- "invalid unsizing between {:?} -> {:?}",
- src.layout.ty,
- cast_ty.ty
- );
- }
- return self.unsize_into_ptr(
- src,
- dest,
- src.layout.ty.boxed_ty(),
- cast_ty.ty.boxed_ty(),
- );
- }
// unsizing of generic struct with pointer fields
// Example: `Arc<T>` -> `Arc<Trait>`
#[inline(always)]
pub fn cur_span(&self) -> Span {
- self.stack()
- .iter()
- .rev()
- .find(|frame| !frame.instance.def.requires_caller_location(*self.tcx))
- .map_or(self.tcx.span, |f| f.current_span())
+ // This deliberately does *not* honor `requires_caller_location` since it is used for much
+ // more than just panics.
+ self.stack().last().map_or(self.tcx.span, |f| f.current_span())
}
#[inline(always)]
#[must_use]
pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
let mut frames = Vec::new();
- for frame in self
- .stack()
- .iter()
- .rev()
- .skip_while(|frame| frame.instance.def.requires_caller_location(*self.tcx))
- {
+ // This deliberately does *not* honor `requires_caller_location` since it is used for much
+ // more than just panics.
+ for frame in self.stack().iter().rev() {
let lint_root = frame.current_source_info().and_then(|source_info| {
match &frame.body.source_scopes[source_info.scope].local_data {
mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
Ok(true)
}
ty::Adt(def, ..) if def.is_box() => {
- self.check_safe_pointer(value, "box")?;
+ let unique = self.ecx.operand_field(value, 0)?;
+ let nonnull = self.ecx.operand_field(&unique, 0)?;
+ let ptr = self.ecx.operand_field(&nonnull, 0)?;
+ self.check_safe_pointer(&ptr, "box")?;
+
+ // Check other fields of Box
+ self.walk_value(value)?;
Ok(true)
}
ty::FnPtr(_sig) => {
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
providers.const_caller_location = const_eval::const_caller_location;
- providers.try_destructure_const = |tcx, val| const_eval::try_destructure_const(tcx, val);
providers.eval_to_valtree = |tcx, param_env_and_value| {
let (param_env, raw) = param_env_and_value.into_parts();
const_eval::eval_to_valtree(tcx, param_env, raw)
rayon = { version = "0.4.0", package = "rustc-rayon", optional = true }
rayon-core = { version = "0.4.0", package = "rustc-rayon-core", optional = true }
rustc-hash = "1.1.0"
-smallvec = { version = "1.6.1", features = ["const_generics", "union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] }
rustc_index = { path = "../rustc_index", package = "rustc_index" }
bitflags = "1.2.1"
measureme = "10.0.0"
#![feature(intrinsics)]
extern "rust-intrinsic" {
- fn atomic_fence(); // ok!
+ fn atomic_fence_seqcst(); // ok!
}
fn main() {
unsafe {
- atomic_fence();
+ atomic_fence_seqcst();
}
}
```
--- /dev/null
+borrowck-move-unsized =
+ cannot move a value of type `{$ty}`
+ .label = the size of `{$ty}` cannot be statically determined
+
+borrowck-higher-ranked-lifetime-error =
+ higher-ranked lifetime error
+
+borrowck-could-not-prove =
+ could not prove `{$predicate}`
+
+borrowck-could-not-normalize =
+ could not normalize `{$value}`
+
+borrowck-higher-ranked-subtype-error =
+ higher-ranked subtype error
+
+generic-does-not-live-long-enough =
+ `{$kind}` does not live long enough
\ No newline at end of file
privacy => "../locales/en-US/privacy.ftl",
typeck => "../locales/en-US/typeck.ftl",
builtin_macros => "../locales/en-US/builtin_macros.ftl",
+ borrowck => "../locales/en-US/borrowck.ftl",
}
pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES};
let message = bundle.get_message(&identifier).expect("missing diagnostic in fluent bundle");
let value = match attr {
Some(attr) => {
- message.get_attribute(attr).expect("missing attribute in fluent message").value()
+ if let Some(attr) = message.get_attribute(attr) {
+ attr.value()
+ } else {
+ panic!("missing attribute `{attr}` in fluent message `{identifier}`")
+ }
+ }
+ None => {
+ if let Some(value) = message.value() {
+ value
+ } else {
+ panic!("missing value in fluent message `{identifier}`")
+ }
}
- None => message.value().expect("missing value in fluent message"),
};
let mut err = vec![];
rustc_lexer = { path = "../rustc_lexer" }
rustc_parse = { path = "../rustc_parse" }
rustc_session = { path = "../rustc_session" }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_ast = { path = "../rustc_ast" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_ast = { path = "../rustc_ast" }
tracing = "0.1"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
odht = { version = "0.3.1", features = ["nightly"] }
arrayvec = { version = "0.7", default-features = false }
rustc_serialize = { path = "../rustc_serialize" }
rustc_macros = { path = "../rustc_macros" }
-smallvec = "1"
+smallvec = "1.8.1"
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
)
| (&ty::Infer(ty::InferTy::TyVar(_)), _)
| (_, &ty::Infer(ty::InferTy::TyVar(_))) => true,
- (&ty::Ref(reg_a, ty_a, mut_a), &ty::Ref(reg_b, ty_b, mut_b)) => {
- reg_a == reg_b && mut_a == mut_b && same_type_modulo_infer(*ty_a, *ty_b)
+ (&ty::Ref(_, ty_a, mut_a), &ty::Ref(_, ty_b, mut_b)) => {
+ mut_a == mut_b && same_type_modulo_infer(*ty_a, *ty_b)
}
_ => a == b,
}
tracing = "0.1"
rustc-rayon-core = { version = "0.4.0", optional = true }
rayon = { version = "0.4.0", package = "rustc-rayon", optional = true }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_ast = { path = "../rustc_ast" }
rustc_attr = { path = "../rustc_attr" }
rustc_borrowck = { path = "../rustc_borrowck" }
odht = { version = "0.3.1", features = ["nightly"] }
snap = "1"
tracing = "0.1"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_middle = { path = "../rustc_middle" }
rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
use std::iter::TrustedLen;
use std::mem;
use std::num::NonZeroUsize;
-use std::path::Path;
+use std::path::PathBuf;
use tracing::debug;
pub(super) use cstore_impl::provide;
//
// NOTE: if you update this, you might need to also update bootstrap's code for generating
// the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`.
- let virtual_rust_source_base_dir = option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR")
- .map(Path::new)
- .filter(|_| {
- // Only spend time on further checks if we have what to translate *to*.
- sess.opts.real_rust_source_base_dir.is_some()
- // Some tests need the translation to be always skipped.
- && sess.opts.debugging_opts.translate_remapped_path_to_local_path
- })
- .filter(|virtual_dir| {
- // Don't translate away `/rustc/$hash` if we're still remapping to it,
- // since that means we're still building `std`/`rustc` that need it,
- // and we don't want the real path to leak into codegen/debuginfo.
- !sess.opts.remap_path_prefix.iter().any(|(_from, to)| to == virtual_dir)
- });
+ let virtual_rust_source_base_dir = [
+ option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(PathBuf::from),
+ sess.opts.debugging_opts.simulate_remapped_rust_src_base.clone(),
+ ]
+ .into_iter()
+ .filter(|_| {
+ // Only spend time on further checks if we have what to translate *to*.
+ sess.opts.real_rust_source_base_dir.is_some()
+ // Some tests need the translation to be always skipped.
+ && sess.opts.debugging_opts.translate_remapped_path_to_local_path
+ })
+ .flatten()
+ .filter(|virtual_dir| {
+ // Don't translate away `/rustc/$hash` if we're still remapping to it,
+ // since that means we're still building `std`/`rustc` that need it,
+ // and we don't want the real path to leak into codegen/debuginfo.
+ !sess.opts.remap_path_prefix.iter().any(|(_from, to)| to == virtual_dir)
+ })
+ .collect::<Vec<_>>();
+
let try_to_translate_virtual_to_real = |name: &mut rustc_span::FileName| {
debug!(
"try_to_translate_virtual_to_real(name={:?}): \
name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir,
);
- if let Some(virtual_dir) = virtual_rust_source_base_dir {
+ for virtual_dir in &virtual_rust_source_base_dir {
if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
if let rustc_span::FileName::Real(old_name) = name {
if let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
rustc_ast = { path = "../rustc_ast" }
rustc_span = { path = "../rustc_span" }
chalk-ir = "0.80.0"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_session = { path = "../rustc_session" }
rustc_type_ir = { path = "../rustc_type_ir" }
rand = "0.8.4"
}
impl<'tcx> TyCtxt<'tcx> {
- /// Destructure a type-level constant ADT or array into its variant index and its field values.
- /// Panics if the destructuring fails, use `try_destructure_const` for fallible version.
- pub fn destructure_const(self, const_: ty::Const<'tcx>) -> ty::DestructuredConst<'tcx> {
- self.try_destructure_const(const_).unwrap()
- }
-
/// Destructure a mir constant ADT or array into its variant index and its field values.
- /// Panics if the destructuring fails, use `try_destructure_const` for fallible version.
+ /// Panics if the destructuring fails, use `try_destructure_mir_constant` for fallible version.
pub fn destructure_mir_constant(
self,
param_env: ty::ParamEnv<'tcx>,
desc { "converting type-level constant value to mir constant value"}
}
- /// Destructure a constant ADT or array into its variant index and its
- /// field values or return `None` if constant is invalid.
- ///
- /// Use infallible `TyCtxt::destructure_const` when you know that constant is valid.
- query try_destructure_const(key: ty::Const<'tcx>) -> Option<ty::DestructuredConst<'tcx>> {
+ /// Destructures array, ADT or tuple constants into the constants
+ /// of their fields.
+ query destructure_const(key: ty::Const<'tcx>) -> ty::DestructuredConst<'tcx> {
desc { "destructuring type level constant"}
}
ObjectTypeBound(Ty<'tcx>, ty::Region<'tcx>),
/// Obligation incurred due to an object cast.
- ObjectCastObligation(/* Object type */ Ty<'tcx>),
+ ObjectCastObligation(/* Concrete type */ Ty<'tcx>, /* Object type */ Ty<'tcx>),
/// Obligation incurred due to a coercion.
Coercion {
p!(write("{:?}", String::from_utf8_lossy(bytes)));
return Ok(self);
}
- _ => {}
+ _ => {
+ p!("&");
+ p!(pretty_print_const_valtree(valtree, *inner_ty, print_ty));
+ return Ok(self);
+ }
},
(ty::ValTree::Branch(_), ty::Array(t, _)) if *t == u8_type => {
let bytes = valtree.try_to_raw_bytes(self.tcx(), *t).unwrap_or_else(|| {
}
// Aggregates, printed as array/tuple/struct/variant construction syntax.
(ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => {
- let Some(contents) = self.tcx().try_destructure_const(
- ty::Const::from_value(self.tcx(), valtree, ty)
- ) else {
- // Fall back to debug pretty printing for invalid constants.
- p!(write("{:?}", valtree));
- if print_ty {
- p!(": ", print(ty));
- }
- return Ok(self);
- };
+ let contents =
+ self.tcx().destructure_const(ty::Const::from_value(self.tcx(), valtree, ty));
let fields = contents.fields.iter().copied();
match *ty.kind() {
ty::Array(..) => {
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_ast = { path = "../rustc_ast" }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
let opt_ty_info;
let self_arg;
if let Some(ref fn_decl) = tcx.hir().fn_decl_by_hir_id(owner_id) {
- opt_ty_info = fn_decl.inputs.get(index).map(|ty| ty.span);
+ opt_ty_info = fn_decl
+ .inputs
+ .get(index)
+ // Make sure that inferred closure args have no type span
+ .and_then(|ty| if arg.pat.span != ty.span { Some(ty.span) } else { None });
self_arg = if index == 0 && fn_decl.implicit_self.has_implicit_self() {
match fn_decl.implicit_self {
hir::ImplicitSelfKind::Imm => Some(ImplicitSelfKind::Imm),
[dependencies]
polonius-engine = "0.13.0"
regex = "1"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
[dependencies]
itertools = "0.10.1"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
rustc_ast = { path = "../rustc_ast" }
rustc_attr = { path = "../rustc_attr" }
})
}
-/// Determine whether this type may be a reference (or box), and thus needs retagging.
-fn may_be_reference(ty: Ty<'_>) -> bool {
+/// Determine whether this type may contain a reference (or box), and thus needs retagging.
+/// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this.
+fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool {
match ty.kind() {
// Primitive types that are not references
ty::Bool
// References
ty::Ref(..) => true,
ty::Adt(..) if ty.is_box() => true,
- // Compound types are not references
- ty::Array(..) | ty::Slice(..) | ty::Tuple(..) | ty::Adt(..) => false,
+ // Compound types: recurse
+ ty::Array(ty, _) | ty::Slice(ty) => {
+ // This does not branch so we keep the depth the same.
+ may_contain_reference(*ty, depth, tcx)
+ }
+ ty::Tuple(tys) => {
+ depth == 0 || tys.iter().any(|ty| may_contain_reference(ty, depth - 1, tcx))
+ }
+ ty::Adt(adt, subst) => {
+ depth == 0
+ || adt.variants().iter().any(|v| {
+ v.fields.iter().any(|f| may_contain_reference(f.ty(tcx, subst), depth - 1, tcx))
+ })
+ }
// Conservative fallback
_ => true,
}
// FIXME: Instead of giving up for unstable places, we should introduce
// a temporary and retag on that.
is_stable(place.as_ref())
- && may_be_reference(place.ty(&*local_decls, tcx).ty)
+ && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx)
&& is_not_temp(&local_decls[place.local])
};
let place_base_raw = |place: &Place<'tcx>| {
doctest = false
[dependencies]
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_hir = { path = "../rustc_hir" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
parking_lot = "0.11"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
[features]
rustc_use_parallel_compiler = ["rustc-rayon-core"]
rustc_query_system = { path = "../rustc_query_system" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
[dependencies]
indexmap = "1.8.0"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
[dev-dependencies]
rustc_macros = { path = "../rustc_macros" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
- Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs }))
+ Ok(inner.map(|inner| AbstractConst { inner, substs: tcx.erase_regions(uv.substs) }))
}
pub fn from_const(
// `AbstractConst`s should not contain any promoteds as they require references which
// are not allowed.
assert_eq!(ct.promoted, None);
+ assert_eq!(ct, self.tcx.erase_regions(ct));
}
}
}
err.span_label(span, explanation);
}
- if let ObligationCauseCode::ObjectCastObligation(obj_ty) = obligation.cause.code().peel_derives() &&
- let Some(self_ty) = trait_predicate.self_ty().no_bound_vars() &&
+ if let ObligationCauseCode::ObjectCastObligation(concrete_ty, obj_ty) = obligation.cause.code().peel_derives() &&
Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
- self.suggest_borrowing_for_object_cast(&mut err, &obligation, self_ty, *obj_ty);
+ self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty);
}
if trait_predicate.is_const_if_const() && obligation.param_env.is_const() {
obligation.cause.code().peel_derives(),
ObligationCauseCode::ItemObligation(_)
| ObligationCauseCode::BindingObligation(_, _)
- | ObligationCauseCode::ObjectCastObligation(_)
+ | ObligationCauseCode::ObjectCastObligation(..)
| ObligationCauseCode::OpaqueType
);
if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
err.span_note(tcx.def_span(item_def_id), &descr);
}
}
- ObligationCauseCode::ObjectCastObligation(object_ty) => {
+ ObligationCauseCode::ObjectCastObligation(concrete_ty, object_ty) => {
err.note(&format!(
- "required for the cast to the object type `{}`",
+ "required for the cast from `{}` to the object type `{}`",
+ self.ty_to_string(concrete_ty),
self.ty_to_string(object_ty)
));
}
let cause = ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
- ObjectCastObligation(target),
+ ObjectCastObligation(source, target),
);
let outlives = ty::OutlivesPredicate(r_a, r_b);
nested.push(Obligation::with_depth(
let cause = ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
- ObjectCastObligation(target),
+ ObjectCastObligation(source, target),
);
let outlives = ty::OutlivesPredicate(r_a, r_b);
nested.push(Obligation::with_depth(
let cause = ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
- ObjectCastObligation(target),
+ ObjectCastObligation(source, target),
);
let predicate_to_obligation = |predicate| {
chalk-ir = "0.80.0"
chalk-engine = "0.80.0"
chalk-solve = "0.80.0"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_infer = { path = "../rustc_infer" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
--- /dev/null
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_target::abi::VariantIdx;
+
+use std::iter;
+
+/// Destructures array, ADT or tuple constants into the constants
+/// of their fields.
+pub(crate) fn destructure_const<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ const_: ty::Const<'tcx>,
+) -> ty::DestructuredConst<'tcx> {
+ let ty::ConstKind::Value(valtree) = const_.kind() else {
+ bug!("cannot destructure constant {:?}", const_)
+ };
+
+ let branches = match valtree {
+ ty::ValTree::Branch(b) => b,
+ _ => bug!("cannot destructure constant {:?}", const_),
+ };
+
+ let (fields, variant) = match const_.ty().kind() {
+ ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
+ // construct the consts for the elements of the array/slice
+ let field_consts = branches
+ .iter()
+ .map(|b| tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Value(*b), ty: *inner_ty }))
+ .collect::<Vec<_>>();
+ debug!(?field_consts);
+
+ (field_consts, None)
+ }
+ ty::Adt(def, _) if def.variants().is_empty() => bug!("unreachable"),
+ ty::Adt(def, substs) => {
+ let (variant_idx, branches) = if def.is_enum() {
+ let (head, rest) = branches.split_first().unwrap();
+ (VariantIdx::from_u32(head.unwrap_leaf().try_to_u32().unwrap()), rest)
+ } else {
+ (VariantIdx::from_u32(0), branches)
+ };
+ let fields = &def.variant(variant_idx).fields;
+ let mut field_consts = Vec::with_capacity(fields.len());
+
+ for (field, field_valtree) in iter::zip(fields, branches) {
+ let field_ty = field.ty(tcx, substs);
+ let field_const = tcx.mk_const(ty::ConstS {
+ kind: ty::ConstKind::Value(*field_valtree),
+ ty: field_ty,
+ });
+ field_consts.push(field_const);
+ }
+ debug!(?field_consts);
+
+ (field_consts, Some(variant_idx))
+ }
+ ty::Tuple(elem_tys) => {
+ let fields = iter::zip(*elem_tys, branches)
+ .map(|(elem_ty, elem_valtree)| {
+ tcx.mk_const(ty::ConstS {
+ kind: ty::ConstKind::Value(*elem_valtree),
+ ty: elem_ty,
+ })
+ })
+ .collect::<Vec<_>>();
+
+ (fields, None)
+ }
+ _ => bug!("cannot destructure constant {:?}", const_),
+ };
+
+ let fields = tcx.arena.alloc_from_iter(fields.into_iter());
+
+ ty::DestructuredConst { variant, fields }
+}
+
+pub fn provide(providers: &mut ty::query::Providers) {
+ *providers = ty::query::Providers { destructure_const, ..*providers };
+}
mod assoc;
mod common_traits;
+mod consts;
pub mod instance;
mod needs_drop;
pub mod representability;
pub fn provide(providers: &mut Providers) {
assoc::provide(providers);
common_traits::provide(providers);
+ consts::provide(providers);
needs_drop::provide(providers);
ty::provide(providers);
instance::provide(providers);
rustc_serialize = { path = "../rustc_serialize" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_macros = { path = "../rustc_macros" }
-smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_target = { path = "../rustc_target" }
rustc_session = { path = "../rustc_session" }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_ast = { path = "../rustc_ast" }
rustc_span = { path = "../rustc_span" }
rustc_index = { path = "../rustc_index" }
use std::cmp;
+use rustc_index::vec::IndexVec;
use rustc_middle::ty::error::TypeError;
+rustc_index::newtype_index! {
+ pub(crate) struct ExpectedIdx {
+ DEBUG_FORMAT = "ExpectedIdx({})",
+ }
+}
+
+rustc_index::newtype_index! {
+ pub(crate) struct ProvidedIdx {
+ DEBUG_FORMAT = "ProvidedIdx({})",
+ }
+}
+
+impl ExpectedIdx {
+ pub fn to_provided_idx(self) -> ProvidedIdx {
+ ProvidedIdx::from_usize(self.as_usize())
+ }
+}
+
// An issue that might be found in the compatibility matrix
#[derive(Debug)]
enum Issue {
#[derive(Debug)]
pub(crate) enum Error<'tcx> {
/// The provided argument is the invalid type for the expected input
- Invalid(usize, usize, Compatibility<'tcx>), // provided, expected
+ Invalid(ProvidedIdx, ExpectedIdx, Compatibility<'tcx>),
/// There is a missing input
- Missing(usize),
+ Missing(ExpectedIdx),
/// There's a superfluous argument
- Extra(usize),
+ Extra(ProvidedIdx),
/// Two arguments should be swapped
- Swap(usize, usize, usize, usize),
+ Swap(ProvidedIdx, ProvidedIdx, ExpectedIdx, ExpectedIdx),
/// Several arguments should be reordered
- Permutation(Vec<(usize, usize)>), // dest_arg, dest_input
+ Permutation(Vec<(ExpectedIdx, ProvidedIdx)>),
}
pub(crate) struct ArgMatrix<'tcx> {
/// Maps the indices in the `compatibility_matrix` rows to the indices of
/// the *user provided* inputs
- input_indexes: Vec<usize>,
+ provided_indices: Vec<ProvidedIdx>,
/// Maps the indices in the `compatibility_matrix` columns to the indices
/// of the *expected* args
- arg_indexes: Vec<usize>,
+ expected_indices: Vec<ExpectedIdx>,
/// The first dimension (rows) are the remaining user provided inputs to
/// match and the second dimension (cols) are the remaining expected args
/// to match
}
impl<'tcx> ArgMatrix<'tcx> {
- pub(crate) fn new<F: FnMut(usize, usize) -> Compatibility<'tcx>>(
- minimum_input_count: usize,
- provided_arg_count: usize,
+ pub(crate) fn new<F: FnMut(ProvidedIdx, ExpectedIdx) -> Compatibility<'tcx>>(
+ provided_count: usize,
+ expected_input_count: usize,
mut is_compatible: F,
) -> Self {
- let compatibility_matrix = (0..provided_arg_count)
- .map(|i| (0..minimum_input_count).map(|j| is_compatible(i, j)).collect())
+ let compatibility_matrix = (0..provided_count)
+ .map(|i| {
+ (0..expected_input_count)
+ .map(|j| is_compatible(ProvidedIdx::from_usize(i), ExpectedIdx::from_usize(j)))
+ .collect()
+ })
.collect();
ArgMatrix {
- input_indexes: (0..provided_arg_count).collect(),
- arg_indexes: (0..minimum_input_count).collect(),
+ provided_indices: (0..provided_count).map(ProvidedIdx::from_usize).collect(),
+ expected_indices: (0..expected_input_count).map(ExpectedIdx::from_usize).collect(),
compatibility_matrix,
}
}
/// Remove a given input from consideration
- fn eliminate_input(&mut self, idx: usize) {
- self.input_indexes.remove(idx);
+ fn eliminate_provided(&mut self, idx: usize) {
+ self.provided_indices.remove(idx);
self.compatibility_matrix.remove(idx);
}
/// Remove a given argument from consideration
- fn eliminate_arg(&mut self, idx: usize) {
- self.arg_indexes.remove(idx);
+ fn eliminate_expected(&mut self, idx: usize) {
+ self.expected_indices.remove(idx);
for row in &mut self.compatibility_matrix {
row.remove(idx);
}
}
/// "satisfy" an input with a given arg, removing both from consideration
- fn satisfy_input(&mut self, input_idx: usize, arg_idx: usize) {
- self.eliminate_input(input_idx);
- self.eliminate_arg(arg_idx);
+ fn satisfy_input(&mut self, provided_idx: usize, expected_idx: usize) {
+ self.eliminate_provided(provided_idx);
+ self.eliminate_expected(expected_idx);
}
// Returns a `Vec` of (user input, expected arg) of matched arguments. These
// are inputs on the remaining diagonal that match.
- fn eliminate_satisfied(&mut self) -> Vec<(usize, usize)> {
- let mut i = cmp::min(self.input_indexes.len(), self.arg_indexes.len());
+ fn eliminate_satisfied(&mut self) -> Vec<(ProvidedIdx, ExpectedIdx)> {
+ let num_args = cmp::min(self.provided_indices.len(), self.expected_indices.len());
let mut eliminated = vec![];
- while i > 0 {
- let idx = i - 1;
- if matches!(self.compatibility_matrix[idx][idx], Compatibility::Compatible) {
- eliminated.push((self.input_indexes[idx], self.arg_indexes[idx]));
- self.satisfy_input(idx, idx);
+ for i in (0..num_args).rev() {
+ if matches!(self.compatibility_matrix[i][i], Compatibility::Compatible) {
+ eliminated.push((self.provided_indices[i], self.expected_indices[i]));
+ self.satisfy_input(i, i);
}
- i -= 1;
}
- return eliminated;
+ eliminated
}
// Find some issue in the compatibility matrix
fn find_issue(&self) -> Option<Issue> {
let mat = &self.compatibility_matrix;
- let ai = &self.arg_indexes;
- let ii = &self.input_indexes;
+ let ai = &self.expected_indices;
+ let ii = &self.provided_indices;
for i in 0..cmp::max(ai.len(), ii.len()) {
// If we eliminate the last row, any left-over inputs are considered missing
//
// We'll want to know which arguments and inputs these rows and columns correspond to
// even after we delete them.
- pub(crate) fn find_errors(mut self) -> (Vec<Error<'tcx>>, Vec<Option<usize>>) {
- let provided_arg_count = self.input_indexes.len();
+ pub(crate) fn find_errors(
+ mut self,
+ ) -> (Vec<Error<'tcx>>, IndexVec<ExpectedIdx, Option<ProvidedIdx>>) {
+ let provided_arg_count = self.provided_indices.len();
let mut errors: Vec<Error<'tcx>> = vec![];
// For each expected argument, the matched *actual* input
- let mut matched_inputs: Vec<Option<usize>> = vec![None; self.arg_indexes.len()];
+ let mut matched_inputs: IndexVec<ExpectedIdx, Option<ProvidedIdx>> =
+ IndexVec::from_elem_n(None, self.expected_indices.len());
// Before we start looking for issues, eliminate any arguments that are already satisfied,
// so that an argument which is already spoken for by the input it's in doesn't
// Without this elimination, the first argument causes the second argument
// to show up as both a missing input and extra argument, rather than
// just an invalid type.
- for (inp, arg) in self.eliminate_satisfied() {
- matched_inputs[arg] = Some(inp);
+ for (provided, expected) in self.eliminate_satisfied() {
+ matched_inputs[expected] = Some(provided);
}
- while self.input_indexes.len() > 0 || self.arg_indexes.len() > 0 {
+ while !self.provided_indices.is_empty() || !self.expected_indices.is_empty() {
match self.find_issue() {
Some(Issue::Invalid(idx)) => {
let compatibility = self.compatibility_matrix[idx][idx].clone();
- let input_idx = self.input_indexes[idx];
- let arg_idx = self.arg_indexes[idx];
+ let input_idx = self.provided_indices[idx];
+ let arg_idx = self.expected_indices[idx];
self.satisfy_input(idx, idx);
errors.push(Error::Invalid(input_idx, arg_idx, compatibility));
}
Some(Issue::Extra(idx)) => {
- let input_idx = self.input_indexes[idx];
- self.eliminate_input(idx);
+ let input_idx = self.provided_indices[idx];
+ self.eliminate_provided(idx);
errors.push(Error::Extra(input_idx));
}
Some(Issue::Missing(idx)) => {
- let arg_idx = self.arg_indexes[idx];
- self.eliminate_arg(idx);
+ let arg_idx = self.expected_indices[idx];
+ self.eliminate_expected(idx);
errors.push(Error::Missing(arg_idx));
}
Some(Issue::Swap(idx, other)) => {
- let input_idx = self.input_indexes[idx];
- let other_input_idx = self.input_indexes[other];
- let arg_idx = self.arg_indexes[idx];
- let other_arg_idx = self.arg_indexes[other];
+ let input_idx = self.provided_indices[idx];
+ let other_input_idx = self.provided_indices[other];
+ let arg_idx = self.expected_indices[idx];
+ let other_arg_idx = self.expected_indices[other];
let (min, max) = (cmp::min(idx, other), cmp::max(idx, other));
self.satisfy_input(min, max);
// Subtract 1 because we already removed the "min" row
Some(Issue::Permutation(args)) => {
let mut idxs: Vec<usize> = args.iter().filter_map(|&a| a).collect();
- let mut real_idxs = vec![None; provided_arg_count];
+ let mut real_idxs: IndexVec<ProvidedIdx, Option<(ExpectedIdx, ProvidedIdx)>> =
+ IndexVec::from_elem_n(None, provided_arg_count);
for (src, dst) in
args.iter().enumerate().filter_map(|(src, dst)| dst.map(|dst| (src, dst)))
{
- let src_input_idx = self.input_indexes[src];
- let dst_input_idx = self.input_indexes[dst];
- let dest_arg_idx = self.arg_indexes[dst];
+ let src_input_idx = self.provided_indices[src];
+ let dst_input_idx = self.provided_indices[dst];
+ let dest_arg_idx = self.expected_indices[dst];
real_idxs[src_input_idx] = Some((dest_arg_idx, dst_input_idx));
matched_inputs[dest_arg_idx] = Some(src_input_idx);
}
use crate::astconv::AstConv;
use crate::check::coercion::CoerceMany;
-use crate::check::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error};
+use crate::check::fn_ctxt::arg_matrix::{
+ ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx,
+};
use crate::check::gather_locals::Declaration;
use crate::check::method::MethodCallee;
use crate::check::Expectation::*;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{ExprKind, Node, QPath};
+use rustc_index::vec::IndexVec;
use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
use rustc_infer::infer::InferOk;
use rustc_infer::infer::TypeTrace;
use rustc_middle::ty::adjustment::AllowTwoPhase;
-use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::symbol::Ident;
use rustc_span::{self, Span};
use std::iter;
use std::slice;
-enum TupleMatchFound {
- None,
- Single,
- /// Beginning and end Span
- Multiple(Span, Span),
-}
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn check_casts(&self) {
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
let minimum_input_count = expected_input_tys.len();
let provided_arg_count = provided_args.len();
- // We'll also want to keep track of the fully coerced argument types, for an awkward hack near the end
- let mut final_arg_types: Vec<Option<(Ty<'_>, Ty<'_>)>> = vec![None; provided_arg_count];
-
// We introduce a helper function to demand that a given argument satisfy a given input
// This is more complicated than just checking type equality, as arguments could be coerced
// This version writes those types back so further type checking uses the narrowed types
- let demand_compatible = |idx, final_arg_types: &mut Vec<Option<(Ty<'tcx>, Ty<'tcx>)>>| {
+ let demand_compatible = |idx| {
let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
let provided_arg = &provided_args[idx];
// `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
- // Keep track of these for below
- final_arg_types[idx] = Some((checked_ty, coerced_ty));
-
// Cause selection errors caused by resolving a single argument to point at the
// argument and not the call. This lets us customize the span pointed to in the
// fulfillment error to be more accurate.
self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
self.point_at_arg_instead_of_call_if_possible(
errors,
- &final_arg_types,
call_expr,
call_span,
provided_args,
+ &expected_input_tys,
);
});
- // Make sure we store the resolved type
- final_arg_types[idx] = Some((checked_ty, coerced_ty));
-
let coerce_error = self
.try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
.err();
}
};
- // A "softer" version of the helper above, which checks types without persisting them,
- // and treats error types differently
- // This will allow us to "probe" for other argument orders that would likely have been correct
- let check_compatible = |input_idx, arg_idx| {
- let formal_input_ty: Ty<'tcx> = formal_input_tys[arg_idx];
- let expected_input_ty: Ty<'tcx> = expected_input_tys[arg_idx];
-
- // If either is an error type, we defy the usual convention and consider them to *not* be
- // coercible. This prevents our error message heuristic from trying to pass errors into
- // every argument.
- if formal_input_ty.references_error() || expected_input_ty.references_error() {
- return Compatibility::Incompatible(None);
- }
-
- let provided_arg: &hir::Expr<'tcx> = &provided_args[input_idx];
- let expectation = Expectation::rvalue_hint(self, expected_input_ty);
- // FIXME: check that this is safe; I don't believe this commits any of the obligations, but I can't be sure.
- //
- // I had another method of "soft" type checking before,
- // but it was failing to find the type of some expressions (like "")
- // so I prodded this method and made it pub(super) so I could call it, and it seems to work well.
- let checked_ty = self.check_expr_kind(provided_arg, expectation);
-
- let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
- let can_coerce = self.can_coerce(checked_ty, coerced_ty);
-
- if !can_coerce {
- return Compatibility::Incompatible(None);
- }
-
- let subtyping_result = self
- .at(&self.misc(provided_arg.span), self.param_env)
- .sup(formal_input_ty, coerced_ty);
-
- // Same as above: if either the coerce type or the checked type is an error type,
- // consider them *not* compatible.
- let coercible =
- !coerced_ty.references_error() && !checked_ty.references_error() && can_coerce;
-
- match (coercible, &subtyping_result) {
- (true, Ok(_)) => Compatibility::Compatible,
- _ => Compatibility::Incompatible(subtyping_result.err()),
- }
- };
-
// To start, we only care "along the diagonal", where we expect every
// provided arg to be in the right spot
- let mut compatibility = vec![Compatibility::Incompatible(None); provided_args.len()];
+ let mut compatibility_diagonal =
+ vec![Compatibility::Incompatible(None); provided_args.len()];
// Keep track of whether we *could possibly* be satisfied, i.e. whether we're on the happy path
// if the wrong number of arguments were supplied, we CAN'T be satisfied,
self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
self.point_at_arg_instead_of_call_if_possible(
errors,
- &final_arg_types,
call_expr,
call_span,
&provided_args,
+ &expected_input_tys,
);
})
}
continue;
}
- let compatible = demand_compatible(idx, &mut final_arg_types);
+ let compatible = demand_compatible(idx);
let is_compatible = matches!(compatible, Compatibility::Compatible);
- compatibility[idx] = compatible;
+ compatibility_diagonal[idx] = compatible;
if !is_compatible {
call_appears_satisfied = false;
}
}
- // Logic here is a bit hairy
- 'errors: {
- // If something above didn't typecheck, we've fallen off the happy path
- // and we should make some effort to provide better error messages
- if call_appears_satisfied {
- break 'errors;
- }
-
- self.set_tainted_by_errors();
+ if c_variadic && provided_arg_count < minimum_input_count {
+ err_code = "E0060";
+ }
- // The algorithm here is inspired by levenshtein distance and longest common subsequence.
- // We'll try to detect 4 different types of mistakes:
- // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
- // - An input is missing, which isn't satisfied by *any* of the other arguments
- // - Some number of arguments have been provided in the wrong order
- // - A type is straight up invalid
+ for arg in provided_args.iter().skip(minimum_input_count) {
+ // Make sure we've checked this expr at least once.
+ let arg_ty = self.check_expr(&arg);
- // First, let's find the errors
- let mut compatibility: Vec<_> = compatibility.into_iter().map(Some).collect();
- let (mut errors, matched_inputs) =
- ArgMatrix::new(minimum_input_count, provided_arg_count, |i, j| {
- if i == j { compatibility[i].take().unwrap() } else { check_compatible(i, j) }
- })
- .find_errors();
+ // If the function is c-style variadic, we skipped a bunch of arguments
+ // so we need to check those, and write out the types
+ // Ideally this would be folded into the above, for uniform style
+ // but c-variadic is already a corner case
+ if c_variadic {
+ fn variadic_error<'tcx>(
+ sess: &'tcx Session,
+ span: Span,
+ ty: Ty<'tcx>,
+ cast_ty: &str,
+ ) {
+ use crate::structured_errors::MissingCastForVariadicArg;
- // Okay, so here's where it gets complicated in regards to what errors
- // we emit and how.
- // There are 3 different "types" of errors we might encounter.
- // 1) Missing/extra/swapped arguments
- // 2) Valid but incorrect arguments
- // 3) Invalid arguments
- // - Currently I think this only comes up with `CyclicTy`
- //
- // We first need to go through, remove those from (3) and emit those
- // as their own error, particularly since they're error code and
- // message is special. From what I can tell, we *must* emit these
- // here (vs somewhere prior to this function) since the arguments
- // become invalid *because* of how they get used in the function.
- // It is what it is.
-
- let found_errors = !errors.is_empty();
-
- errors.drain_filter(|error| {
- let Error::Invalid(input_idx, arg_idx, Compatibility::Incompatible(Some(e))) = error else { return false };
- let expected_ty = expected_input_tys[*arg_idx];
- let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap_or_else(|| tcx.ty_error());
- let cause = &self.misc(provided_args[*input_idx].span);
- let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
- if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
- self.report_and_explain_type_error(trace, e).emit();
- return true;
+ MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
}
- false
- });
- // We're done if we found errors, but we already emitted them.
- // I don't think we *should* be able to enter this bit of code
- // (`!call_appears_satisfied`) without *also* finding errors, but we
- // don't want to accidentally not emit an error if there is some
- // logic bug in the `ArgMatrix` code.
- if found_errors && errors.is_empty() {
- break 'errors;
+ // There are a few types which get autopromoted when passed via varargs
+ // in C but we just error out instead and require explicit casts.
+ let arg_ty = self.structurally_resolved_type(arg.span, arg_ty);
+ match arg_ty.kind() {
+ ty::Float(ty::FloatTy::F32) => {
+ variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
+ }
+ ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
+ variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
+ }
+ ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
+ variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
+ }
+ ty::FnDef(..) => {
+ let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx));
+ let ptr_ty = self.resolve_vars_if_possible(ptr_ty);
+ variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
+ }
+ _ => {}
+ }
}
+ }
+ if !call_appears_satisfied {
// Next, let's construct the error
let (error_span, full_call_span, ctor_of) = match &call_expr.kind {
hir::ExprKind::Call(
Some(CtorOf::Variant) => "enum variant",
None => "function",
};
- if c_variadic && provided_arg_count < minimum_input_count {
- err_code = "E0060";
+
+ let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal);
+ let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic {
+ minimum_input_count
+ } else {
+ provided_arg_count
+ }));
+ debug_assert_eq!(
+ formal_input_tys.len(),
+ expected_input_tys.len(),
+ "expected formal_input_tys to be the same size as expected_input_tys"
+ );
+ let formal_and_expected_inputs = IndexVec::from_iter(
+ formal_input_tys
+ .iter()
+ .copied()
+ .zip(expected_input_tys.iter().copied())
+ .map(|vars| self.resolve_vars_if_possible(vars)),
+ );
+
+ self.report_arg_errors(
+ compatibility_diagonal,
+ formal_and_expected_inputs,
+ provided_args,
+ full_call_span,
+ error_span,
+ args_span,
+ call_name,
+ c_variadic,
+ err_code,
+ fn_def_id,
+ );
+ }
+ }
+
+ fn report_arg_errors(
+ &self,
+ compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
+ formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
+ provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
+ full_call_span: Span,
+ error_span: Span,
+ args_span: Span,
+ call_name: &str,
+ c_variadic: bool,
+ err_code: &str,
+ fn_def_id: Option<DefId>,
+ ) {
+ // Don't print if it has error types or is just plain `_`
+ fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
+ tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
+ }
+
+ self.set_tainted_by_errors();
+ let tcx = self.tcx;
+
+ // A "softer" version of the `demand_compatible`, which checks types without persisting them,
+ // and treats error types differently
+ // This will allow us to "probe" for other argument orders that would likely have been correct
+ let check_compatible = |provided_idx: ProvidedIdx, expected_idx: ExpectedIdx| {
+ if provided_idx.as_usize() == expected_idx.as_usize() {
+ return compatibility_diagonal[provided_idx].clone();
}
- // Next special case: The case where we expect a single tuple and
- // wrapping all the args in parentheses (or adding a comma to
- // already existing parentheses) will result in a tuple that
- // satisfies the call.
- // This isn't super ideal code, because we copy code from elsewhere
- // and somewhat duplicate this. We also delegate to the general type
- // mismatch suggestions for the single arg case.
- let sugg_tuple_wrap_args =
- self.suggested_tuple_wrap(&expected_input_tys, provided_args);
- match sugg_tuple_wrap_args {
- TupleMatchFound::None => {}
- TupleMatchFound::Single => {
- let expected_ty = expected_input_tys[0];
- let provided_ty = final_arg_types[0].map(|ty| ty.0).unwrap();
- let expected_ty = self.resolve_vars_if_possible(expected_ty);
- let provided_ty = self.resolve_vars_if_possible(provided_ty);
- let cause = &self.misc(provided_args[0].span);
- let compatibility = demand_compatible(0, &mut final_arg_types);
- let type_error = match compatibility {
- Compatibility::Incompatible(Some(error)) => error,
- _ => TypeError::Mismatch,
- };
- let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
- let mut err = self.report_and_explain_type_error(trace, &type_error);
- self.emit_coerce_suggestions(
- &mut err,
- &provided_args[0],
- final_arg_types[0].map(|ty| ty.0).unwrap(),
- final_arg_types[0].map(|ty| ty.1).unwrap(),
- None,
- None,
- );
- err.span_label(
- full_call_span,
- format!("arguments to this {} are incorrect", call_name),
- );
- // Call out where the function is defined
- label_fn_like(tcx, &mut err, fn_def_id);
- err.emit();
- break 'errors;
+ let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx];
+ // If either is an error type, we defy the usual convention and consider them to *not* be
+ // coercible. This prevents our error message heuristic from trying to pass errors into
+ // every argument.
+ if (formal_input_ty, expected_input_ty).references_error() {
+ return Compatibility::Incompatible(None);
+ }
+
+ let provided_arg: &hir::Expr<'tcx> = &provided_args[provided_idx];
+ let expectation = Expectation::rvalue_hint(self, expected_input_ty);
+ // FIXME: check that this is safe; I don't believe this commits any of the obligations, but I can't be sure.
+ //
+ // I had another method of "soft" type checking before,
+ // but it was failing to find the type of some expressions (like "")
+ // so I prodded this method and made it pub(super) so I could call it, and it seems to work well.
+ let checked_ty = self.check_expr_kind(provided_arg, expectation);
+
+ let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
+ let can_coerce = self.can_coerce(checked_ty, coerced_ty);
+ if !can_coerce {
+ return Compatibility::Incompatible(None);
+ }
+
+ // Using probe here, since we don't want this subtyping to affect inference.
+ let subtyping_error = self.probe(|_| {
+ self.at(&self.misc(provided_arg.span), self.param_env)
+ .sup(formal_input_ty, coerced_ty)
+ .err()
+ });
+
+ // Same as above: if either the coerce type or the checked type is an error type,
+ // consider them *not* compatible.
+ let references_error = (coerced_ty, checked_ty).references_error();
+ match (references_error, subtyping_error) {
+ (false, None) => Compatibility::Compatible,
+ (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
+ }
+ };
+
+ // The algorithm here is inspired by levenshtein distance and longest common subsequence.
+ // We'll try to detect 4 different types of mistakes:
+ // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
+ // - An input is missing, which isn't satisfied by *any* of the other arguments
+ // - Some number of arguments have been provided in the wrong order
+ // - A type is straight up invalid
+
+ // First, let's find the errors
+ let (mut errors, matched_inputs) =
+ ArgMatrix::new(provided_args.len(), formal_and_expected_inputs.len(), check_compatible)
+ .find_errors();
+
+ // Precompute the provided types and spans, since that's all we typically need for below
+ let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args
+ .iter()
+ .map(|expr| {
+ let ty = self
+ .typeck_results
+ .borrow()
+ .expr_ty_adjusted_opt(*expr)
+ .unwrap_or_else(|| tcx.ty_error());
+ (self.resolve_vars_if_possible(ty), expr.span)
+ })
+ .collect();
+
+ // First, check if we just need to wrap some arguments in a tuple.
+ if let Some((mismatch_idx, terr)) =
+ compatibility_diagonal.iter().enumerate().find_map(|(i, c)| {
+ if let Compatibility::Incompatible(Some(terr)) = c { Some((i, terr)) } else { None }
+ })
+ {
+ // Is the first bad expected argument a tuple?
+ // Do we have as many extra provided arguments as the tuple's length?
+ // If so, we might have just forgotten to wrap some args in a tuple.
+ if let Some(ty::Tuple(tys)) =
+ formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind())
+ && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
+ {
+ // Wrap up the N provided arguments starting at this position in a tuple.
+ let provided_as_tuple = tcx.mk_tup(
+ provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx).take(tys.len()),
+ );
+
+ let mut satisfied = true;
+ // Check if the newly wrapped tuple + rest of the arguments are compatible.
+ for ((_, expected_ty), provided_ty) in std::iter::zip(
+ formal_and_expected_inputs.iter().skip(mismatch_idx),
+ [provided_as_tuple].into_iter().chain(
+ provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()),
+ ),
+ ) {
+ if !self.can_coerce(provided_ty, *expected_ty) {
+ satisfied = false;
+ break;
+ }
}
- TupleMatchFound::Multiple(start, end) => {
- let mut err = tcx.sess.struct_span_err_with_code(
- full_call_span,
- &format!(
- "this {} takes {}{} but {} {} supplied",
- call_name,
- if c_variadic { "at least " } else { "" },
- potentially_plural_count(minimum_input_count, "argument"),
- potentially_plural_count(provided_arg_count, "argument"),
- if provided_arg_count == 1 { "was" } else { "were" }
- ),
- DiagnosticId::Error(err_code.to_owned()),
- );
- // Call out where the function is defined
+
+ // If they're compatible, suggest wrapping in an arg, and we're done!
+ // Take some care with spans, so we don't suggest wrapping a macro's
+ // innards in parenthesis, for example.
+ if satisfied
+ && let Some(lo) =
+ provided_args[mismatch_idx.into()].span.find_ancestor_inside(error_span)
+ && let Some(hi) = provided_args[(mismatch_idx + tys.len() - 1).into()]
+ .span
+ .find_ancestor_inside(error_span)
+ {
+ let mut err;
+ if tys.len() == 1 {
+ // A tuple wrap suggestion actually occurs within,
+ // so don't do anything special here.
+ err = self.report_and_explain_type_error(
+ TypeTrace::types(
+ &self.misc(lo),
+ true,
+ formal_and_expected_inputs[mismatch_idx.into()].1,
+ provided_arg_tys[mismatch_idx.into()].0,
+ ),
+ terr,
+ );
+ err.span_label(
+ full_call_span,
+ format!("arguments to this {} are incorrect", call_name),
+ );
+ } else {
+ err = tcx.sess.struct_span_err_with_code(
+ full_call_span,
+ &format!(
+ "this {} takes {}{} but {} {} supplied",
+ call_name,
+ if c_variadic { "at least " } else { "" },
+ potentially_plural_count(
+ formal_and_expected_inputs.len(),
+ "argument"
+ ),
+ potentially_plural_count(provided_args.len(), "argument"),
+ if provided_args.len() == 1 { "was" } else { "were" }
+ ),
+ DiagnosticId::Error(err_code.to_owned()),
+ );
+ err.multipart_suggestion_verbose(
+ "wrap these arguments in parentheses to construct a tuple",
+ vec![
+ (lo.shrink_to_lo(), "(".to_string()),
+ (hi.shrink_to_hi(), ")".to_string()),
+ ],
+ Applicability::MachineApplicable,
+ );
+ };
label_fn_like(tcx, &mut err, fn_def_id);
- err.multipart_suggestion(
- "use parentheses to construct a tuple",
- vec![(start, '('.to_string()), (end, ')'.to_string())],
- Applicability::MachineApplicable,
- );
err.emit();
- break 'errors;
+ return;
}
}
+ }
+
+ // Okay, so here's where it gets complicated in regards to what errors
+ // we emit and how.
+ // There are 3 different "types" of errors we might encounter.
+ // 1) Missing/extra/swapped arguments
+ // 2) Valid but incorrect arguments
+ // 3) Invalid arguments
+ // - Currently I think this only comes up with `CyclicTy`
+ //
+ // We first need to go through, remove those from (3) and emit those
+ // as their own error, particularly since they're error code and
+ // message is special. From what I can tell, we *must* emit these
+ // here (vs somewhere prior to this function) since the arguments
+ // become invalid *because* of how they get used in the function.
+ // It is what it is.
+
+ if errors.is_empty() {
+ if cfg!(debug_assertions) {
+ span_bug!(error_span, "expected errors from argument matrix");
+ } else {
+ tcx.sess
+ .struct_span_err(
+ error_span,
+ "argument type mismatch was detected, \
+ but rustc had trouble determining where",
+ )
+ .note(
+ "we would appreciate a bug report: \
+ https://github.com/rust-lang/rust/issues/new",
+ )
+ .emit();
+ }
+ return;
+ }
+
+ errors.drain_filter(|error| {
+ let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(error)) = error else { return false };
+ let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
+ let (expected_ty, _) = formal_and_expected_inputs[*expected_idx];
+ let cause = &self.misc(provided_span);
+ let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
+ if let Some(e) = error {
+ if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
+ self.report_and_explain_type_error(trace, e).emit();
+ return true;
+ }
+ }
+ false
+ });
+
+ // We're done if we found errors, but we already emitted them.
+ if errors.is_empty() {
+ return;
+ }
+
+ // Okay, now that we've emitted the special errors separately, we
+ // are only left missing/extra/swapped and mismatched arguments, both
+ // can be collated pretty easily if needed.
+
+ // Next special case: if there is only one "Incompatible" error, just emit that
+ if let [
+ Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
+ ] = &errors[..]
+ {
+ let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
+ let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
+ let cause = &self.misc(provided_arg_span);
+ let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
+ let mut err = self.report_and_explain_type_error(trace, err);
+ self.emit_coerce_suggestions(
+ &mut err,
+ &provided_args[*provided_idx],
+ provided_ty,
+ Expectation::rvalue_hint(self, expected_ty)
+ .only_has_type(self)
+ .unwrap_or(formal_ty),
+ None,
+ None,
+ );
+ err.span_label(
+ full_call_span,
+ format!("arguments to this {} are incorrect", call_name),
+ );
+ // Call out where the function is defined
+ label_fn_like(tcx, &mut err, fn_def_id);
+ err.emit();
+ return;
+ }
+
+ let mut err = if formal_and_expected_inputs.len() == provided_args.len() {
+ struct_span_err!(
+ tcx.sess,
+ full_call_span,
+ E0308,
+ "arguments to this {} are incorrect",
+ call_name,
+ )
+ } else {
+ tcx.sess.struct_span_err_with_code(
+ full_call_span,
+ &format!(
+ "this {} takes {}{} but {} {} supplied",
+ call_name,
+ if c_variadic { "at least " } else { "" },
+ potentially_plural_count(formal_and_expected_inputs.len(), "argument"),
+ potentially_plural_count(provided_args.len(), "argument"),
+ if provided_args.len() == 1 { "was" } else { "were" }
+ ),
+ DiagnosticId::Error(err_code.to_owned()),
+ )
+ };
+
+ // As we encounter issues, keep track of what we want to provide for the suggestion
+ let mut labels = vec![];
+ // If there is a single error, we give a specific suggestion; otherwise, we change to
+ // "did you mean" with the suggested function call
+ enum SuggestionText {
+ None,
+ Provide(bool),
+ Remove(bool),
+ Swap,
+ Reorder,
+ DidYouMean,
+ }
+ let mut suggestion_text = SuggestionText::None;
+
+ let mut errors = errors.into_iter().peekable();
+ while let Some(error) = errors.next() {
+ match error {
+ Error::Invalid(provided_idx, expected_idx, compatibility) => {
+ let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
+ let (provided_ty, provided_span) = provided_arg_tys[provided_idx];
+ if let Compatibility::Incompatible(error) = &compatibility {
+ let cause = &self.misc(provided_span);
+ let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
+ if let Some(e) = error {
+ self.note_type_err(
+ &mut err,
+ &trace.cause,
+ None,
+ Some(trace.values),
+ e,
+ false,
+ true,
+ );
+ }
+ }
- // Okay, now that we've emitted the special errors separately, we
- // are only left missing/extra/swapped and mismatched arguments, both
- // can be collated pretty easily if needed.
-
- // Next special case: if there is only one "Incompatible" error, just emit that
- if errors.len() == 1 {
- if let Some(Error::Invalid(
- input_idx,
- arg_idx,
- Compatibility::Incompatible(Some(error)),
- )) = errors.iter().next()
- {
- let expected_ty = expected_input_tys[*arg_idx];
- let provided_ty = final_arg_types[*input_idx]
- .map(|ty| ty.0)
- .unwrap_or_else(|| tcx.ty_error());
- let expected_ty = self.resolve_vars_if_possible(expected_ty);
- let provided_ty = self.resolve_vars_if_possible(provided_ty);
- let cause = &self.misc(provided_args[*input_idx].span);
- let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
- let mut err = self.report_and_explain_type_error(trace, error);
self.emit_coerce_suggestions(
&mut err,
- &provided_args[*input_idx],
+ &provided_args[provided_idx],
provided_ty,
- final_arg_types[*input_idx]
- .map(|ty| ty.1)
- .unwrap_or_else(|| tcx.ty_error()),
+ Expectation::rvalue_hint(self, expected_ty)
+ .only_has_type(self)
+ .unwrap_or(formal_ty),
None,
None,
);
- err.span_label(
- full_call_span,
- format!("arguments to this {} are incorrect", call_name),
- );
- // Call out where the function is defined
- label_fn_like(tcx, &mut err, fn_def_id);
- err.emit();
- break 'errors;
}
- }
-
- let mut err = if minimum_input_count == provided_arg_count {
- struct_span_err!(
- tcx.sess,
- full_call_span,
- E0308,
- "arguments to this {} are incorrect",
- call_name,
- )
- } else {
- tcx.sess.struct_span_err_with_code(
- full_call_span,
- &format!(
- "this {} takes {}{} but {} {} supplied",
- call_name,
- if c_variadic { "at least " } else { "" },
- potentially_plural_count(minimum_input_count, "argument"),
- potentially_plural_count(provided_arg_count, "argument"),
- if provided_arg_count == 1 { "was" } else { "were" }
- ),
- DiagnosticId::Error(err_code.to_owned()),
- )
- };
-
- // As we encounter issues, keep track of what we want to provide for the suggestion
- let mut labels = vec![];
- // If there is a single error, we give a specific suggestion; otherwise, we change to
- // "did you mean" with the suggested function call
- enum SuggestionText {
- None,
- Provide(bool),
- Remove(bool),
- Swap,
- Reorder,
- DidYouMean,
- }
- let mut suggestion_text = SuggestionText::None;
-
- let mut errors = errors.into_iter().peekable();
- while let Some(error) = errors.next() {
- match error {
- Error::Invalid(input_idx, arg_idx, compatibility) => {
- let expected_ty = expected_input_tys[arg_idx];
- let provided_ty = final_arg_types[input_idx]
- .map(|ty| ty.0)
- .unwrap_or_else(|| tcx.ty_error());
- let expected_ty = self.resolve_vars_if_possible(expected_ty);
- let provided_ty = self.resolve_vars_if_possible(provided_ty);
- if let Compatibility::Incompatible(error) = &compatibility {
- let cause = &self.misc(provided_args[input_idx].span);
- let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
- if let Some(e) = error {
- self.note_type_err(
- &mut err,
- &trace.cause,
- None,
- Some(trace.values),
- e,
- false,
- true,
- );
- }
+ Error::Extra(arg_idx) => {
+ let (provided_ty, provided_span) = provided_arg_tys[arg_idx];
+ let provided_ty_name = if !has_error_or_infer([provided_ty]) {
+ // FIXME: not suggestable, use something else
+ format!(" of type `{}`", provided_ty)
+ } else {
+ "".to_string()
+ };
+ labels
+ .push((provided_span, format!("argument{} unexpected", provided_ty_name)));
+ suggestion_text = match suggestion_text {
+ SuggestionText::None => SuggestionText::Remove(false),
+ SuggestionText::Remove(_) => SuggestionText::Remove(true),
+ _ => SuggestionText::DidYouMean,
+ };
+ }
+ Error::Missing(expected_idx) => {
+ // If there are multiple missing arguments adjacent to each other,
+ // then we can provide a single error.
+
+ let mut missing_idxs = vec![expected_idx];
+ while let Some(e) = errors.next_if(|e| {
+ matches!(e, Error::Missing(next_expected_idx)
+ if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
+ }) {
+ match e {
+ Error::Missing(expected_idx) => missing_idxs.push(expected_idx),
+ _ => unreachable!(),
}
-
- self.emit_coerce_suggestions(
- &mut err,
- &provided_args[input_idx],
- provided_ty,
- // FIXME(compiler-errors): expected_ty?
- final_arg_types[input_idx]
- .map(|ty| ty.1)
- .unwrap_or_else(|| tcx.ty_error()),
- None,
- None,
- );
}
- Error::Extra(arg_idx) => {
- let arg_type = if let Some((_, ty)) = final_arg_types[arg_idx] {
- if ty.references_error() || ty.has_infer_types() {
- "".into()
+
+ // NOTE: Because we might be re-arranging arguments, might have extra
+ // arguments, etc. it's hard to *really* know where we should provide
+ // this error label, so as a heuristic, we point to the provided arg, or
+ // to the call if the missing inputs pass the provided args.
+ match &missing_idxs[..] {
+ &[expected_idx] => {
+ let (_, input_ty) = formal_and_expected_inputs[expected_idx];
+ let span = if let Some((_, arg_span)) =
+ provided_arg_tys.get(expected_idx.to_provided_idx())
+ {
+ *arg_span
} else {
- format!(" of type `{}`", ty)
- }
- } else {
- "".into()
- };
- labels.push((
- provided_args[arg_idx].span,
- format!("argument{} unexpected", arg_type),
- ));
- suggestion_text = match suggestion_text {
- SuggestionText::None => SuggestionText::Remove(false),
- SuggestionText::Remove(_) => SuggestionText::Remove(true),
- _ => SuggestionText::DidYouMean,
- };
- }
- Error::Missing(input_idx) => {
- // If there are multiple missing arguments adjacent to each other,
- // then we can provide a single error.
-
- let mut missing_idxs = vec![input_idx];
- while let Some(e) = errors.next_if(|e| matches!(e, Error::Missing(input_idx) if *input_idx == (missing_idxs.last().unwrap() + 1))) {
- match e {
- Error::Missing(input_idx) => missing_idxs.push(input_idx),
- _ => unreachable!(),
- }
+ args_span
+ };
+ let rendered = if !has_error_or_infer([input_ty]) {
+ format!(" of type `{}`", input_ty)
+ } else {
+ "".to_string()
+ };
+ labels.push((span, format!("an argument{} is missing", rendered)));
+ suggestion_text = match suggestion_text {
+ SuggestionText::None => SuggestionText::Provide(false),
+ SuggestionText::Provide(_) => SuggestionText::Provide(true),
+ _ => SuggestionText::DidYouMean,
+ };
}
-
- // NOTE: Because we might be re-arranging arguments, might have extra
- // arguments, etc. it's hard to *really* know where we should provide
- // this error label, so as a heuristic, we point to the provided arg, or
- // to the call if the missing inputs pass the provided args.
- match &missing_idxs[..] {
- &[input_idx] => {
- let expected_ty = expected_input_tys[input_idx];
- let input_ty = self.resolve_vars_if_possible(expected_ty);
- let span = if input_idx < provided_arg_count {
- let arg_span = provided_args[input_idx].span;
- Span::new(arg_span.lo(), arg_span.hi(), arg_span.ctxt(), None)
- } else {
- args_span
- };
- let arg_type =
- if input_ty.references_error() || input_ty.has_infer_types() {
- "".into()
- } else {
- format!(" of type `{}`", input_ty)
- };
- labels.push((span, format!("an argument{} is missing", arg_type)));
- suggestion_text = match suggestion_text {
- SuggestionText::None => SuggestionText::Provide(false),
- SuggestionText::Provide(_) => SuggestionText::Provide(true),
- _ => SuggestionText::DidYouMean,
- };
- }
- &[first_idx, second_idx] => {
- let first_input_ty =
- self.resolve_vars_if_possible(expected_input_tys[first_idx]);
- let second_input_ty =
- self.resolve_vars_if_possible(expected_input_tys[second_idx]);
-
- let span = if second_idx < provided_arg_count {
- let first_arg_span = provided_args[first_idx].span;
- let second_arg_span = provided_args[second_idx].span;
- Span::new(
- first_arg_span.lo(),
- second_arg_span.hi(),
- first_arg_span.ctxt(),
- None,
- )
- } else {
- args_span
- };
- let any_unnameable = false
- || first_input_ty.references_error()
- || first_input_ty.has_infer_types()
- || second_input_ty.references_error()
- || second_input_ty.has_infer_types();
- let arg_type = if any_unnameable {
- "".into()
- } else {
+ &[first_idx, second_idx] => {
+ let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
+ let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
+ let span = if let (Some((_, first_span)), Some((_, second_span))) = (
+ provided_arg_tys.get(first_idx.to_provided_idx()),
+ provided_arg_tys.get(second_idx.to_provided_idx()),
+ ) {
+ first_span.to(*second_span)
+ } else {
+ args_span
+ };
+ let rendered =
+ if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
format!(
" of type `{}` and `{}`",
- first_input_ty, second_input_ty
- )
- };
- labels
- .push((span, format!("two arguments{} are missing", arg_type)));
- suggestion_text = match suggestion_text {
- SuggestionText::None | SuggestionText::Provide(_) => {
- SuggestionText::Provide(true)
- }
- _ => SuggestionText::DidYouMean,
- };
- }
- &[first_idx, second_idx, third_idx] => {
- let first_input_ty =
- self.resolve_vars_if_possible(expected_input_tys[first_idx]);
- let second_input_ty =
- self.resolve_vars_if_possible(expected_input_tys[second_idx]);
- let third_input_ty =
- self.resolve_vars_if_possible(expected_input_tys[third_idx]);
- let span = if third_idx < provided_arg_count {
- let first_arg_span = provided_args[first_idx].span;
- let third_arg_span = provided_args[third_idx].span;
- Span::new(
- first_arg_span.lo(),
- third_arg_span.hi(),
- first_arg_span.ctxt(),
- None,
- )
- } else {
- args_span
- };
- let any_unnameable = false
- || first_input_ty.references_error()
- || first_input_ty.has_infer_types()
- || second_input_ty.references_error()
- || second_input_ty.has_infer_types()
- || third_input_ty.references_error()
- || third_input_ty.has_infer_types();
- let arg_type = if any_unnameable {
- "".into()
- } else {
- format!(
- " of type `{}`, `{}`, and `{}`",
- first_input_ty, second_input_ty, third_input_ty
- )
- };
- labels.push((
- span,
- format!("three arguments{} are missing", arg_type),
- ));
- suggestion_text = match suggestion_text {
- SuggestionText::None | SuggestionText::Provide(_) => {
- SuggestionText::Provide(true)
- }
- _ => SuggestionText::DidYouMean,
- };
- }
- missing_idxs => {
- let first_idx = *missing_idxs.first().unwrap();
- let last_idx = *missing_idxs.last().unwrap();
- // NOTE: Because we might be re-arranging arguments, might have extra arguments, etc.
- // It's hard to *really* know where we should provide this error label, so this is a
- // decent heuristic
- let span = if last_idx < provided_arg_count {
- let first_arg_span = provided_args[first_idx].span;
- let last_arg_span = provided_args[last_idx].span;
- Span::new(
- first_arg_span.lo(),
- last_arg_span.hi(),
- first_arg_span.ctxt(),
- None,
+ first_expected_ty, second_expected_ty
)
} else {
- // Otherwise just label the whole function
- args_span
- };
- labels.push((span, format!("multiple arguments are missing")));
- suggestion_text = match suggestion_text {
- SuggestionText::None | SuggestionText::Provide(_) => {
- SuggestionText::Provide(true)
- }
- _ => SuggestionText::DidYouMean,
+ "".to_string()
};
- }
+ labels.push((span, format!("two arguments{} are missing", rendered)));
+ suggestion_text = match suggestion_text {
+ SuggestionText::None | SuggestionText::Provide(_) => {
+ SuggestionText::Provide(true)
+ }
+ _ => SuggestionText::DidYouMean,
+ };
}
- }
- Error::Swap(input_idx, other_input_idx, arg_idx, other_arg_idx) => {
- let first_span = provided_args[input_idx].span;
- let second_span = provided_args[other_input_idx].span;
-
- let first_expected_ty =
- self.resolve_vars_if_possible(expected_input_tys[arg_idx]);
- let first_provided_ty = if let Some((ty, _)) = final_arg_types[input_idx] {
- format!(", found `{}`", ty)
- } else {
- String::new()
- };
- labels.push((
- first_span,
- format!("expected `{}`{}", first_expected_ty, first_provided_ty),
- ));
- let other_expected_ty =
- self.resolve_vars_if_possible(expected_input_tys[other_arg_idx]);
- let other_provided_ty =
- if let Some((ty, _)) = final_arg_types[other_input_idx] {
- format!(", found `{}`", ty)
+ &[first_idx, second_idx, third_idx] => {
+ let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
+ let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
+ let (_, third_expected_ty) = formal_and_expected_inputs[third_idx];
+ let span = if let (Some((_, first_span)), Some((_, third_span))) = (
+ provided_arg_tys.get(first_idx.to_provided_idx()),
+ provided_arg_tys.get(third_idx.to_provided_idx()),
+ ) {
+ first_span.to(*third_span)
} else {
- String::new()
+ args_span
};
- labels.push((
- second_span,
- format!("expected `{}`{}", other_expected_ty, other_provided_ty),
- ));
- suggestion_text = match suggestion_text {
- SuggestionText::None => SuggestionText::Swap,
- _ => SuggestionText::DidYouMean,
- };
- }
- Error::Permutation(args) => {
- for (dst_arg, dest_input) in args {
- let expected_ty =
- self.resolve_vars_if_possible(expected_input_tys[dst_arg]);
- let provided_ty = if let Some((ty, _)) = final_arg_types[dest_input] {
- format!(", found `{}`", ty)
+ let rendered = if !has_error_or_infer([
+ first_expected_ty,
+ second_expected_ty,
+ third_expected_ty,
+ ]) {
+ format!(
+ " of type `{}`, `{}`, and `{}`",
+ first_expected_ty, second_expected_ty, third_expected_ty
+ )
} else {
- String::new()
+ "".to_string()
+ };
+ labels.push((span, format!("three arguments{} are missing", rendered)));
+ suggestion_text = match suggestion_text {
+ SuggestionText::None | SuggestionText::Provide(_) => {
+ SuggestionText::Provide(true)
+ }
+ _ => SuggestionText::DidYouMean,
+ };
+ }
+ missing_idxs => {
+ let first_idx = *missing_idxs.first().unwrap();
+ let last_idx = *missing_idxs.last().unwrap();
+ // NOTE: Because we might be re-arranging arguments, might have extra arguments, etc.
+ // It's hard to *really* know where we should provide this error label, so this is a
+ // decent heuristic
+ let span = if let (Some((_, first_span)), Some((_, last_span))) = (
+ provided_arg_tys.get(first_idx.to_provided_idx()),
+ provided_arg_tys.get(last_idx.to_provided_idx()),
+ ) {
+ first_span.to(*last_span)
+ } else {
+ args_span
+ };
+ labels.push((span, format!("multiple arguments are missing")));
+ suggestion_text = match suggestion_text {
+ SuggestionText::None | SuggestionText::Provide(_) => {
+ SuggestionText::Provide(true)
+ }
+ _ => SuggestionText::DidYouMean,
};
- labels.push((
- provided_args[dest_input].span,
- format!("expected `{}`{}", expected_ty, provided_ty),
- ));
}
-
- suggestion_text = match suggestion_text {
- SuggestionText::None => SuggestionText::Reorder,
- _ => SuggestionText::DidYouMean,
- };
}
}
- }
-
- // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
- if labels.len() <= 5 {
- for (span, label) in labels {
- err.span_label(span, label);
- }
- }
-
- // Call out where the function is defined
- label_fn_like(tcx, &mut err, fn_def_id);
-
- // And add a suggestion block for all of the parameters
- let suggestion_text = match suggestion_text {
- SuggestionText::None => None,
- SuggestionText::Provide(plural) => {
- Some(format!("provide the argument{}", if plural { "s" } else { "" }))
- }
- SuggestionText::Remove(plural) => {
- Some(format!("remove the extra argument{}", if plural { "s" } else { "" }))
- }
- SuggestionText::Swap => Some("swap these arguments".to_string()),
- SuggestionText::Reorder => Some("reorder these arguments".to_string()),
- SuggestionText::DidYouMean => Some("did you mean".to_string()),
- };
- if let Some(suggestion_text) = suggestion_text {
- let source_map = self.sess().source_map();
- let mut suggestion = format!(
- "{}(",
- source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| String::new())
- );
- for (arg_index, input_idx) in matched_inputs.iter().enumerate() {
- let suggestion_text = if let Some(input_idx) = input_idx {
- let arg_span = provided_args[*input_idx].span.source_callsite();
- let arg_text = source_map.span_to_snippet(arg_span).unwrap();
- arg_text
+ Error::Swap(
+ first_provided_idx,
+ second_provided_idx,
+ first_expected_idx,
+ second_expected_idx,
+ ) => {
+ let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx];
+ let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx];
+ let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
+ format!(", found `{}`", first_provided_ty)
} else {
- // Propose a placeholder of the correct type
- let expected_ty = expected_input_tys[arg_index];
- let input_ty = self.resolve_vars_if_possible(expected_ty);
- if input_ty.is_unit() {
- "()".to_string()
- } else if !input_ty.is_ty_var() {
- format!("/* {} */", input_ty)
- } else {
- "/* value */".to_string()
- }
+ String::new()
+ };
+ labels.push((
+ first_span,
+ format!("expected `{}`{}", first_expected_ty, first_provided_ty_name),
+ ));
+
+ let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx];
+ let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx];
+ let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
+ format!(", found `{}`", second_provided_ty)
+ } else {
+ String::new()
};
- suggestion += &suggestion_text;
- if arg_index < minimum_input_count - 1 {
- suggestion += ", ";
+ labels.push((
+ second_span,
+ format!("expected `{}`{}", second_expected_ty, second_provided_ty_name),
+ ));
+
+ suggestion_text = match suggestion_text {
+ SuggestionText::None => SuggestionText::Swap,
+ _ => SuggestionText::DidYouMean,
+ };
+ }
+ Error::Permutation(args) => {
+ for (dst_arg, dest_input) in args {
+ let (_, expected_ty) = formal_and_expected_inputs[dst_arg];
+ let (provided_ty, provided_span) = provided_arg_tys[dest_input];
+ let provided_ty_name = if !has_error_or_infer([provided_ty]) {
+ format!(", found `{}`", provided_ty)
+ } else {
+ String::new()
+ };
+ labels.push((
+ provided_span,
+ format!("expected `{}`{}", expected_ty, provided_ty_name),
+ ));
}
+
+ suggestion_text = match suggestion_text {
+ SuggestionText::None => SuggestionText::Reorder,
+ _ => SuggestionText::DidYouMean,
+ };
}
- suggestion += ")";
- err.span_suggestion_verbose(
- error_span,
- &suggestion_text,
- suggestion,
- Applicability::HasPlaceholders,
- );
}
- err.emit();
}
- for arg in provided_args.iter().skip(minimum_input_count) {
- let arg_ty = self.check_expr(&arg);
+ // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
+ if labels.len() <= 5 {
+ for (span, label) in labels {
+ err.span_label(span, label);
+ }
+ }
- // If the function is c-style variadic, we skipped a bunch of arguments
- // so we need to check those, and write out the types
- // Ideally this would be folded into the above, for uniform style
- // but c-variadic is already a corner case
- if c_variadic {
- fn variadic_error<'tcx>(
- sess: &'tcx Session,
- span: Span,
- ty: Ty<'tcx>,
- cast_ty: &str,
- ) {
- use crate::structured_errors::MissingCastForVariadicArg;
+ // Call out where the function is defined
+ label_fn_like(tcx, &mut err, fn_def_id);
- MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
+ // And add a suggestion block for all of the parameters
+ let suggestion_text = match suggestion_text {
+ SuggestionText::None => None,
+ SuggestionText::Provide(plural) => {
+ Some(format!("provide the argument{}", if plural { "s" } else { "" }))
+ }
+ SuggestionText::Remove(plural) => {
+ Some(format!("remove the extra argument{}", if plural { "s" } else { "" }))
+ }
+ SuggestionText::Swap => Some("swap these arguments".to_string()),
+ SuggestionText::Reorder => Some("reorder these arguments".to_string()),
+ SuggestionText::DidYouMean => Some("did you mean".to_string()),
+ };
+ if let Some(suggestion_text) = suggestion_text {
+ let source_map = self.sess().source_map();
+ let mut suggestion = format!(
+ "{}(",
+ source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| fn_def_id
+ .map_or("".to_string(), |fn_def_id| tcx.item_name(fn_def_id).to_string()))
+ );
+ let mut needs_comma = false;
+ for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
+ if needs_comma {
+ suggestion += ", ";
+ } else {
+ needs_comma = true;
}
-
- // There are a few types which get autopromoted when passed via varargs
- // in C but we just error out instead and require explicit casts.
- let arg_ty = self.structurally_resolved_type(arg.span, arg_ty);
- match arg_ty.kind() {
- ty::Float(ty::FloatTy::F32) => {
- variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
- }
- ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
- variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
- }
- ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
- variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
- }
- ty::FnDef(..) => {
- let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx));
- let ptr_ty = self.resolve_vars_if_possible(ptr_ty);
- variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
+ let suggestion_text = if let Some(provided_idx) = provided_idx
+ && let (_, provided_span) = provided_arg_tys[*provided_idx]
+ && let Ok(arg_text) =
+ source_map.span_to_snippet(provided_span.source_callsite())
+ {
+ arg_text
+ } else {
+ // Propose a placeholder of the correct type
+ let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
+ if expected_ty.is_unit() {
+ "()".to_string()
+ } else if expected_ty.is_suggestable(tcx) {
+ format!("/* {} */", expected_ty)
+ } else {
+ "/* value */".to_string()
}
- _ => {}
- }
+ };
+ suggestion += &suggestion_text;
}
+ suggestion += ")";
+ err.span_suggestion_verbose(
+ error_span,
+ &suggestion_text,
+ suggestion,
+ Applicability::HasPlaceholders,
+ );
}
- }
-
- fn suggested_tuple_wrap(
- &self,
- expected_input_tys: &[Ty<'tcx>],
- provided_args: &'tcx [hir::Expr<'tcx>],
- ) -> TupleMatchFound {
- // Only handle the case where we expect only one tuple arg
- let [expected_arg_type] = expected_input_tys[..] else { return TupleMatchFound::None };
- let &ty::Tuple(expected_types) = self.resolve_vars_if_possible(expected_arg_type).kind()
- else { return TupleMatchFound::None };
-
- // First check that there are the same number of types.
- if expected_types.len() != provided_args.len() {
- return TupleMatchFound::None;
- }
-
- let supplied_types: Vec<_> = provided_args.iter().map(|arg| self.check_expr(arg)).collect();
-
- let all_match = iter::zip(expected_types, supplied_types)
- .all(|(expected, supplied)| self.can_eq(self.param_env, expected, supplied).is_ok());
- if !all_match {
- return TupleMatchFound::None;
- }
- match provided_args {
- [] => TupleMatchFound::None,
- [_] => TupleMatchFound::Single,
- [first, .., last] => {
- TupleMatchFound::Multiple(first.span.shrink_to_lo(), last.span.shrink_to_hi())
- }
- }
+ err.emit();
}
// AST fragment checking
fn point_at_arg_instead_of_call_if_possible(
&self,
errors: &mut Vec<traits::FulfillmentError<'tcx>>,
- final_arg_types: &[Option<(Ty<'tcx>, Ty<'tcx>)>],
expr: &'tcx hir::Expr<'tcx>,
call_sp: Span,
args: &'tcx [hir::Expr<'tcx>],
+ expected_tys: &[Ty<'tcx>],
) {
// We *do not* do this for desugared call spans to keep good diagnostics when involving
// the `?` operator.
return;
}
- for error in errors {
+ 'outer: for error in errors {
// Only if the cause is somewhere inside the expression we want try to point at arg.
// Otherwise, it means that the cause is somewhere else and we should not change
// anything because we can break the correct span.
(result_code, code) = (code, parent);
}
}
- let self_: ty::subst::GenericArg<'_> = match unpeel_to_top(error.obligation.cause.code()) {
- ObligationCauseCode::BuiltinDerivedObligation(code) |
- ObligationCauseCode::DerivedObligation(code) => {
- code.parent_trait_pred.self_ty().skip_binder().into()
- }
- ObligationCauseCode::ImplDerivedObligation(code) => {
- code.derived.parent_trait_pred.self_ty().skip_binder().into()
- }
- _ if let ty::PredicateKind::Trait(predicate) =
- error.obligation.predicate.kind().skip_binder() => {
+ let self_: ty::subst::GenericArg<'_> =
+ match unpeel_to_top(error.obligation.cause.code()) {
+ ObligationCauseCode::BuiltinDerivedObligation(code)
+ | ObligationCauseCode::DerivedObligation(code) => {
+ code.parent_trait_pred.self_ty().skip_binder().into()
+ }
+ ObligationCauseCode::ImplDerivedObligation(code) => {
+ code.derived.parent_trait_pred.self_ty().skip_binder().into()
+ }
+ _ if let ty::PredicateKind::Trait(predicate) =
+ error.obligation.predicate.kind().skip_binder() =>
+ {
predicate.self_ty().into()
}
- _ => continue,
- };
+ _ => continue,
+ };
let self_ = self.resolve_vars_if_possible(self_);
+ let ty_matches_self = |ty: Ty<'tcx>| ty.walk().any(|arg| arg == self_);
+
+ let typeck_results = self.typeck_results.borrow();
+
+ for (idx, arg) in args.iter().enumerate() {
+ // Don't adjust the span if we already have a more precise span
+ // within one of the args.
+ if arg.span.contains(error.obligation.cause.span) {
+ let references_arg =
+ typeck_results.expr_ty_opt(arg).map_or(false, &ty_matches_self)
+ || expected_tys.get(idx).copied().map_or(false, &ty_matches_self);
+ if references_arg && !arg.span.from_expansion() {
+ error.obligation.cause.map_code(|parent_code| {
+ ObligationCauseCode::FunctionArgumentObligation {
+ arg_hir_id: args[idx].hir_id,
+ call_hir_id: expr.hir_id,
+ parent_code,
+ }
+ })
+ }
+ continue 'outer;
+ }
+ }
// Collect the argument position for all arguments that could have caused this
// `FulfillmentError`.
- let mut referenced_in = final_arg_types
- .iter()
+ let mut referenced_in: Vec<_> = std::iter::zip(expected_tys, args)
.enumerate()
- .filter_map(|(i, arg)| match arg {
- Some((checked_ty, coerce_ty)) => Some([(i, *checked_ty), (i, *coerce_ty)]),
- _ => None,
+ .flat_map(|(idx, (expected_ty, arg))| {
+ if let Some(arg_ty) = typeck_results.expr_ty_opt(arg) {
+ vec![(idx, arg_ty), (idx, *expected_ty)]
+ } else {
+ vec![]
+ }
})
- .flatten()
- .flat_map(|(i, ty)| {
+ .filter_map(|(i, ty)| {
let ty = self.resolve_vars_if_possible(ty);
// We walk the argument type because the argument's type could have
// been `Option<T>`, but the `FulfillmentError` references `T`.
- if ty.walk().any(|arg| arg == self_) { Some(i) } else { None }
+ if ty_matches_self(ty) { Some(i) } else { None }
})
- .collect::<Vec<usize>>();
+ .collect();
// Both checked and coerced types could have matched, thus we need to remove
// duplicates.
referenced_in.sort_unstable();
referenced_in.dedup();
- if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
+ if let &[idx] = &referenced_in[..] {
// Do not point at the inside of a macro.
// That would often result in poor error messages.
- if args[ref_in].span.from_expansion() {
- return;
+ if args[idx].span.from_expansion() {
+ continue;
}
// We make sure that only *one* argument matches the obligation failure
// and we assign the obligation's span to its expression's.
- error.obligation.cause.span = args[ref_in].span;
+ error.obligation.cause.span = args[idx].span;
error.obligation.cause.map_code(|parent_code| {
ObligationCauseCode::FunctionArgumentObligation {
- arg_hir_id: args[ref_in].hir_id,
+ arg_hir_id: args[idx].hir_id,
call_hir_id: expr.hir_id,
parent_code,
}
}
fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
+ // Skip items with no generics - there's nothing to infer in them.
+ if tcx.generics_of(item_def_id).count() == 0 {
+ return &[];
+ }
+
match tcx.def_kind(item_def_id) {
DefKind::Fn
| DefKind::AssocFn
// by matthieu-m
use crate::alloc::{self, Layout, LayoutError};
use core::fmt::{self, Debug, Display, Formatter};
-use core::marker::{PhantomData, Unsize};
+use core::marker::PhantomData;
+#[cfg(not(no_global_oom_handling))]
+use core::marker::Unsize;
use core::mem;
use core::ops::{Deref, DerefMut};
use core::ptr::Pointee;
Ok(())
}
+ #[cfg(not(no_global_oom_handling))]
fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> {
assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity");
use core::char::{decode_utf16, REPLACEMENT_CHARACTER};
use core::fmt;
use core::hash;
+use core::iter::FusedIterator;
#[cfg(not(no_global_oom_handling))]
-use core::iter::FromIterator;
-use core::iter::{from_fn, FusedIterator};
+use core::iter::{from_fn, FromIterator};
#[cfg(not(no_global_oom_handling))]
use core::ops::Add;
#[cfg(not(no_global_oom_handling))]
};
use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop};
+#[cfg(not(no_global_oom_handling))]
use core::ops::Deref;
use core::ptr::{self, NonNull};
use core::slice::{self};
}
/// Forgets to Drop the remaining elements while still allowing the backing allocation to be freed.
+ #[cfg(not(no_global_oom_handling))]
pub(crate) fn forget_remaining_elements(&mut self) {
self.ptr = self.end;
}
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
target_family = "wasm",
target_arch = "asmjs",
- windows
+ target_os = "uefi",
+ windows,
))]
#[repr(transparent)]
#[unstable(
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
target_family = "wasm",
target_arch = "asmjs",
- windows
+ target_os = "uefi",
+ windows,
))]
#[unstable(
feature = "c_variadic",
#[cfg(all(
target_arch = "aarch64",
not(any(target_os = "macos", target_os = "ios")),
- not(windows)
+ not(target_os = "uefi"),
+ not(windows),
))]
#[repr(C)]
#[derive(Debug)]
}
/// PowerPC ABI implementation of a `va_list`.
-#[cfg(all(target_arch = "powerpc", not(windows)))]
+#[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(
}
/// x86_64 ABI implementation of a `va_list`.
-#[cfg(all(target_arch = "x86_64", not(windows)))]
+#[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
target_family = "wasm",
target_arch = "asmjs",
- windows
+ target_os = "uefi",
+ windows,
))]
inner: VaListImpl<'f>,
any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
not(target_family = "wasm"),
not(target_arch = "asmjs"),
- not(windows)
+ not(target_os = "uefi"),
+ not(windows),
))]
inner: &'a mut VaListImpl<'f>,
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
target_family = "wasm",
target_arch = "asmjs",
- windows
+ target_os = "uefi",
+ windows,
))]
#[unstable(
feature = "c_variadic",
any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
not(target_family = "wasm"),
not(target_arch = "asmjs"),
- not(windows)
+ not(target_os = "uefi"),
+ not(windows),
))]
#[unstable(
feature = "c_variadic",
unsafe { crate::ptr::drop_in_place(to_drop) }
}
+// These have been renamed.
+#[cfg(bootstrap)]
+extern "rust-intrinsic" {
+ pub fn atomic_cxchg<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_acq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_rel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_acqrel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_failacq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_acq_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_acqrel_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_acq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_rel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_acqrel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_failacq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_acq_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_acqrel_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_load<T: Copy>(src: *const T) -> T;
+ pub fn atomic_load_acq<T: Copy>(src: *const T) -> T;
+ pub fn atomic_load_relaxed<T: Copy>(src: *const T) -> T;
+ pub fn atomic_load_unordered<T: Copy>(src: *const T) -> T;
+ pub fn atomic_store<T: Copy>(dst: *mut T, val: T);
+ pub fn atomic_store_rel<T: Copy>(dst: *mut T, val: T);
+ pub fn atomic_store_relaxed<T: Copy>(dst: *mut T, val: T);
+ pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
+ pub fn atomic_xchg<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xchg_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xchg_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xchg_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xchg_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xadd<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xadd_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xadd_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xadd_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xadd_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xsub<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xsub_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xsub_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xsub_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xsub_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_and<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_and_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_and_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_and_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_and_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_nand<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_nand_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_nand_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_nand_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_nand_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_or<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_or_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_or_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_or_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_or_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xor<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xor_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xor_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xor_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xor_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_max<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_max_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_max_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_max_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_max_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_min<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_min_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_min_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_min_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_min_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umin<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umin_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umin_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umin_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umin_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umax<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umax_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umax_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umax_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umax_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_fence();
+ pub fn atomic_fence_acq();
+ pub fn atomic_fence_rel();
+ pub fn atomic_fence_acqrel();
+ pub fn atomic_singlethreadfence();
+ pub fn atomic_singlethreadfence_acq();
+ pub fn atomic_singlethreadfence_rel();
+ pub fn atomic_singlethreadfence_acqrel();
+}
+
+// These have been renamed.
+#[cfg(bootstrap)]
+mod atomics {
+ pub use super::atomic_cxchg as atomic_cxchg_seqcst_seqcst;
+ pub use super::atomic_cxchg_acq as atomic_cxchg_acquire_acquire;
+ pub use super::atomic_cxchg_acq_failrelaxed as atomic_cxchg_acquire_relaxed;
+ pub use super::atomic_cxchg_acqrel as atomic_cxchg_acqrel_acquire;
+ pub use super::atomic_cxchg_acqrel_failrelaxed as atomic_cxchg_acqrel_relaxed;
+ pub use super::atomic_cxchg_failacq as atomic_cxchg_seqcst_acquire;
+ pub use super::atomic_cxchg_failrelaxed as atomic_cxchg_seqcst_relaxed;
+ pub use super::atomic_cxchg_rel as atomic_cxchg_release_relaxed;
+ pub use super::atomic_cxchg_relaxed as atomic_cxchg_relaxed_relaxed;
+
+ pub use super::atomic_cxchgweak as atomic_cxchgweak_seqcst_seqcst;
+ pub use super::atomic_cxchgweak_acq as atomic_cxchgweak_acquire_acquire;
+ pub use super::atomic_cxchgweak_acq_failrelaxed as atomic_cxchgweak_acquire_relaxed;
+ pub use super::atomic_cxchgweak_acqrel as atomic_cxchgweak_acqrel_acquire;
+ pub use super::atomic_cxchgweak_acqrel_failrelaxed as atomic_cxchgweak_acqrel_relaxed;
+ pub use super::atomic_cxchgweak_failacq as atomic_cxchgweak_seqcst_acquire;
+ pub use super::atomic_cxchgweak_failrelaxed as atomic_cxchgweak_seqcst_relaxed;
+ pub use super::atomic_cxchgweak_rel as atomic_cxchgweak_release_relaxed;
+ pub use super::atomic_cxchgweak_relaxed as atomic_cxchgweak_relaxed_relaxed;
+
+ pub use super::atomic_load as atomic_load_seqcst;
+ pub use super::atomic_load_acq as atomic_load_acquire;
+ pub use super::atomic_load_relaxed;
+ pub use super::atomic_load_unordered;
+
+ pub use super::atomic_store as atomic_store_seqcst;
+ pub use super::atomic_store_rel as atomic_store_release;
+ pub use super::atomic_store_relaxed;
+ pub use super::atomic_store_unordered;
+
+ pub use super::atomic_xchg as atomic_xchg_seqcst;
+ pub use super::atomic_xchg_acq as atomic_xchg_acquire;
+ pub use super::atomic_xchg_acqrel;
+ pub use super::atomic_xchg_rel as atomic_xchg_release;
+ pub use super::atomic_xchg_relaxed;
+
+ pub use super::atomic_xadd as atomic_xadd_seqcst;
+ pub use super::atomic_xadd_acq as atomic_xadd_acquire;
+ pub use super::atomic_xadd_acqrel;
+ pub use super::atomic_xadd_rel as atomic_xadd_release;
+ pub use super::atomic_xadd_relaxed;
+
+ pub use super::atomic_xsub as atomic_xsub_seqcst;
+ pub use super::atomic_xsub_acq as atomic_xsub_acquire;
+ pub use super::atomic_xsub_acqrel;
+ pub use super::atomic_xsub_rel as atomic_xsub_release;
+ pub use super::atomic_xsub_relaxed;
+
+ pub use super::atomic_and as atomic_and_seqcst;
+ pub use super::atomic_and_acq as atomic_and_acquire;
+ pub use super::atomic_and_acqrel;
+ pub use super::atomic_and_rel as atomic_and_release;
+ pub use super::atomic_and_relaxed;
+
+ pub use super::atomic_nand as atomic_nand_seqcst;
+ pub use super::atomic_nand_acq as atomic_nand_acquire;
+ pub use super::atomic_nand_acqrel;
+ pub use super::atomic_nand_rel as atomic_nand_release;
+ pub use super::atomic_nand_relaxed;
+
+ pub use super::atomic_or as atomic_or_seqcst;
+ pub use super::atomic_or_acq as atomic_or_acquire;
+ pub use super::atomic_or_acqrel;
+ pub use super::atomic_or_rel as atomic_or_release;
+ pub use super::atomic_or_relaxed;
+
+ pub use super::atomic_xor as atomic_xor_seqcst;
+ pub use super::atomic_xor_acq as atomic_xor_acquire;
+ pub use super::atomic_xor_acqrel;
+ pub use super::atomic_xor_rel as atomic_xor_release;
+ pub use super::atomic_xor_relaxed;
+
+ pub use super::atomic_max as atomic_max_seqcst;
+ pub use super::atomic_max_acq as atomic_max_acquire;
+ pub use super::atomic_max_acqrel;
+ pub use super::atomic_max_rel as atomic_max_release;
+ pub use super::atomic_max_relaxed;
+
+ pub use super::atomic_min as atomic_min_seqcst;
+ pub use super::atomic_min_acq as atomic_min_acquire;
+ pub use super::atomic_min_acqrel;
+ pub use super::atomic_min_rel as atomic_min_release;
+ pub use super::atomic_min_relaxed;
+
+ pub use super::atomic_umin as atomic_umin_seqcst;
+ pub use super::atomic_umin_acq as atomic_umin_acquire;
+ pub use super::atomic_umin_acqrel;
+ pub use super::atomic_umin_rel as atomic_umin_release;
+ pub use super::atomic_umin_relaxed;
+
+ pub use super::atomic_umax as atomic_umax_seqcst;
+ pub use super::atomic_umax_acq as atomic_umax_acquire;
+ pub use super::atomic_umax_acqrel;
+ pub use super::atomic_umax_rel as atomic_umax_release;
+ pub use super::atomic_umax_relaxed;
+
+ pub use super::atomic_fence as atomic_fence_seqcst;
+ pub use super::atomic_fence_acq as atomic_fence_acquire;
+ pub use super::atomic_fence_acqrel;
+ pub use super::atomic_fence_rel as atomic_fence_release;
+
+ pub use super::atomic_singlethreadfence as atomic_singlethreadfence_seqcst;
+ pub use super::atomic_singlethreadfence_acq as atomic_singlethreadfence_acquire;
+ pub use super::atomic_singlethreadfence_acqrel;
+ pub use super::atomic_singlethreadfence_rel as atomic_singlethreadfence_release;
+}
+
+#[cfg(bootstrap)]
+pub use atomics::*;
+
+#[cfg(not(bootstrap))]
extern "rust-intrinsic" {
// N.B., these intrinsics take raw pointers because they mutate aliased
// memory, which is not valid for either `&` or `&mut`.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::SeqCst`] as both the `success` and `failure` parameters.
+ /// [`Ordering::Relaxed`] as both the success and failure parameters.
/// For example, [`AtomicBool::compare_exchange`].
- pub fn atomic_cxchg<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_relaxed_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Acquire`] as both the `success` and `failure` parameters.
+ /// [`Ordering::Relaxed`] and [`Ordering::Acquire`] as the success and failure parameters.
/// For example, [`AtomicBool::compare_exchange`].
- pub fn atomic_cxchg_acq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_relaxed_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Release`] as the `success` and [`Ordering::Relaxed`] as the
- /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
- pub fn atomic_cxchg_rel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// [`Ordering::Relaxed`] and [`Ordering::SeqCst`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange`].
+ pub fn atomic_cxchg_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Acquire`] as the
- /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
- pub fn atomic_cxchg_acqrel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// [`Ordering::Acquire`] and [`Ordering::Relaxed`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange`].
+ pub fn atomic_cxchg_acquire_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Relaxed`] as both the `success` and `failure` parameters.
+ /// [`Ordering::Acquire`] as both the success and failure parameters.
/// For example, [`AtomicBool::compare_exchange`].
- pub fn atomic_cxchg_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_acquire_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Relaxed`] as the
- /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
- pub fn atomic_cxchg_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// [`Ordering::Acquire`] and [`Ordering::SeqCst`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange`].
+ pub fn atomic_cxchg_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Acquire`] as the
- /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
- pub fn atomic_cxchg_failacq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// [`Ordering::Release`] and [`Ordering::Relaxed`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange`].
+ pub fn atomic_cxchg_release_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Acquire`] as the `success` and [`Ordering::Relaxed`] as the
- /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
- pub fn atomic_cxchg_acq_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// [`Ordering::Release`] and [`Ordering::Acquire`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange`].
+ pub fn atomic_cxchg_release_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Relaxed`] as the
- /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
- pub fn atomic_cxchg_acqrel_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// [`Ordering::Release`] and [`Ordering::SeqCst`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange`].
+ pub fn atomic_cxchg_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// Stores a value if the current value is the same as the `old` value.
+ ///
+ /// The stabilized version of this intrinsic is available on the
+ /// [`atomic`] types via the `compare_exchange` method by passing
+ /// [`Ordering::AcqRel`] and [`Ordering::Relaxed`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange`].
+ pub fn atomic_cxchg_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// Stores a value if the current value is the same as the `old` value.
+ ///
+ /// The stabilized version of this intrinsic is available on the
+ /// [`atomic`] types via the `compare_exchange` method by passing
+ /// [`Ordering::AcqRel`] and [`Ordering::Acquire`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange`].
+ pub fn atomic_cxchg_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// Stores a value if the current value is the same as the `old` value.
+ ///
+ /// The stabilized version of this intrinsic is available on the
+ /// [`atomic`] types via the `compare_exchange` method by passing
+ /// [`Ordering::AcqRel`] and [`Ordering::SeqCst`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange`].
+ pub fn atomic_cxchg_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// Stores a value if the current value is the same as the `old` value.
+ ///
+ /// The stabilized version of this intrinsic is available on the
+ /// [`atomic`] types via the `compare_exchange` method by passing
+ /// [`Ordering::SeqCst`] and [`Ordering::Relaxed`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange`].
+ pub fn atomic_cxchg_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// Stores a value if the current value is the same as the `old` value.
+ ///
+ /// The stabilized version of this intrinsic is available on the
+ /// [`atomic`] types via the `compare_exchange` method by passing
+ /// [`Ordering::SeqCst`] and [`Ordering::Acquire`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange`].
+ pub fn atomic_cxchg_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// Stores a value if the current value is the same as the `old` value.
+ ///
+ /// The stabilized version of this intrinsic is available on the
+ /// [`atomic`] types via the `compare_exchange` method by passing
+ /// [`Ordering::SeqCst`] as both the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange`].
+ pub fn atomic_cxchg_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::SeqCst`] as both the `success` and `failure` parameters.
+ /// [`Ordering::Relaxed`] as both the success and failure parameters.
/// For example, [`AtomicBool::compare_exchange_weak`].
- pub fn atomic_cxchgweak<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_relaxed_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Acquire`] as both the `success` and `failure` parameters.
+ /// [`Ordering::Relaxed`] and [`Ordering::Acquire`] as the success and failure parameters.
/// For example, [`AtomicBool::compare_exchange_weak`].
- pub fn atomic_cxchgweak_acq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_relaxed_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Release`] as the `success` and [`Ordering::Relaxed`] as the
- /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
- pub fn atomic_cxchgweak_rel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// [`Ordering::Relaxed`] and [`Ordering::SeqCst`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange_weak`].
+ pub fn atomic_cxchgweak_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Acquire`] as the
- /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
- pub fn atomic_cxchgweak_acqrel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// [`Ordering::Acquire`] and [`Ordering::Relaxed`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange_weak`].
+ pub fn atomic_cxchgweak_acquire_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Relaxed`] as both the `success` and `failure` parameters.
+ /// [`Ordering::Acquire`] as both the success and failure parameters.
/// For example, [`AtomicBool::compare_exchange_weak`].
- pub fn atomic_cxchgweak_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_acquire_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Relaxed`] as the
- /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
- pub fn atomic_cxchgweak_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// [`Ordering::Acquire`] and [`Ordering::SeqCst`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange_weak`].
+ pub fn atomic_cxchgweak_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Acquire`] as the
- /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
- pub fn atomic_cxchgweak_failacq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// [`Ordering::Release`] and [`Ordering::Relaxed`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange_weak`].
+ pub fn atomic_cxchgweak_release_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Acquire`] as the `success` and [`Ordering::Relaxed`] as the
- /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
- pub fn atomic_cxchgweak_acq_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// [`Ordering::Release`] and [`Ordering::Acquire`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange_weak`].
+ pub fn atomic_cxchgweak_release_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Relaxed`] as the
- /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
- pub fn atomic_cxchgweak_acqrel_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// [`Ordering::Release`] and [`Ordering::SeqCst`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange_weak`].
+ pub fn atomic_cxchgweak_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// Stores a value if the current value is the same as the `old` value.
+ ///
+ /// The stabilized version of this intrinsic is available on the
+ /// [`atomic`] types via the `compare_exchange_weak` method by passing
+ /// [`Ordering::AcqRel`] and [`Ordering::Relaxed`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange_weak`].
+ pub fn atomic_cxchgweak_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// Stores a value if the current value is the same as the `old` value.
+ ///
+ /// The stabilized version of this intrinsic is available on the
+ /// [`atomic`] types via the `compare_exchange_weak` method by passing
+ /// [`Ordering::AcqRel`] and [`Ordering::Acquire`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange_weak`].
+ pub fn atomic_cxchgweak_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// Stores a value if the current value is the same as the `old` value.
+ ///
+ /// The stabilized version of this intrinsic is available on the
+ /// [`atomic`] types via the `compare_exchange_weak` method by passing
+ /// [`Ordering::AcqRel`] and [`Ordering::SeqCst`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange_weak`].
+ pub fn atomic_cxchgweak_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// Stores a value if the current value is the same as the `old` value.
+ ///
+ /// The stabilized version of this intrinsic is available on the
+ /// [`atomic`] types via the `compare_exchange_weak` method by passing
+ /// [`Ordering::SeqCst`] and [`Ordering::Relaxed`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange_weak`].
+ pub fn atomic_cxchgweak_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// Stores a value if the current value is the same as the `old` value.
+ ///
+ /// The stabilized version of this intrinsic is available on the
+ /// [`atomic`] types via the `compare_exchange_weak` method by passing
+ /// [`Ordering::SeqCst`] and [`Ordering::Acquire`] as the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange_weak`].
+ pub fn atomic_cxchgweak_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+ /// Stores a value if the current value is the same as the `old` value.
+ ///
+ /// The stabilized version of this intrinsic is available on the
+ /// [`atomic`] types via the `compare_exchange_weak` method by passing
+ /// [`Ordering::SeqCst`] as both the success and failure parameters.
+ /// For example, [`AtomicBool::compare_exchange_weak`].
+ pub fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Loads the current value of the pointer.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `load` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`].
- pub fn atomic_load<T: Copy>(src: *const T) -> T;
+ pub fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
/// Loads the current value of the pointer.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `load` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`].
- pub fn atomic_load_acq<T: Copy>(src: *const T) -> T;
+ pub fn atomic_load_acquire<T: Copy>(src: *const T) -> T;
/// Loads the current value of the pointer.
///
/// The stabilized version of this intrinsic is available on the
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `store` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::store`].
- pub fn atomic_store<T: Copy>(dst: *mut T, val: T);
+ pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T);
/// Stores the value at the specified memory location.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `store` method by passing
/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::store`].
- pub fn atomic_store_rel<T: Copy>(dst: *mut T, val: T);
+ pub fn atomic_store_release<T: Copy>(dst: *mut T, val: T);
/// Stores the value at the specified memory location.
///
/// The stabilized version of this intrinsic is available on the
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `swap` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::swap`].
- pub fn atomic_xchg<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xchg_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
/// Stores the value at the specified memory location, returning the old value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `swap` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::swap`].
- pub fn atomic_xchg_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xchg_acquire<T: Copy>(dst: *mut T, src: T) -> T;
/// Stores the value at the specified memory location, returning the old value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `swap` method by passing
/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::swap`].
- pub fn atomic_xchg_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xchg_release<T: Copy>(dst: *mut T, src: T) -> T;
/// Stores the value at the specified memory location, returning the old value.
///
/// The stabilized version of this intrinsic is available on the
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_add` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_add`].
- pub fn atomic_xadd<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xadd_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
/// Adds to the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_add` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_add`].
- pub fn atomic_xadd_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xadd_acquire<T: Copy>(dst: *mut T, src: T) -> T;
/// Adds to the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_add` method by passing
/// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_add`].
- pub fn atomic_xadd_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xadd_release<T: Copy>(dst: *mut T, src: T) -> T;
/// Adds to the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_sub` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
- pub fn atomic_xsub<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xsub_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
/// Subtract from the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_sub` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
- pub fn atomic_xsub_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xsub_acquire<T: Copy>(dst: *mut T, src: T) -> T;
/// Subtract from the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_sub` method by passing
/// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
- pub fn atomic_xsub_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xsub_release<T: Copy>(dst: *mut T, src: T) -> T;
/// Subtract from the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_and` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_and`].
- pub fn atomic_and<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_and_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
/// Bitwise and with the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_and` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_and`].
- pub fn atomic_and_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_and_acquire<T: Copy>(dst: *mut T, src: T) -> T;
/// Bitwise and with the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_and` method by passing
/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_and`].
- pub fn atomic_and_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_and_release<T: Copy>(dst: *mut T, src: T) -> T;
/// Bitwise and with the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// The stabilized version of this intrinsic is available on the
/// [`AtomicBool`] type via the `fetch_nand` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_nand`].
- pub fn atomic_nand<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_nand_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
/// Bitwise nand with the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// [`AtomicBool`] type via the `fetch_nand` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_nand`].
- pub fn atomic_nand_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_nand_acquire<T: Copy>(dst: *mut T, src: T) -> T;
/// Bitwise nand with the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// [`AtomicBool`] type via the `fetch_nand` method by passing
/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_nand`].
- pub fn atomic_nand_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_nand_release<T: Copy>(dst: *mut T, src: T) -> T;
/// Bitwise nand with the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_or` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_or`].
- pub fn atomic_or<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_or_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
/// Bitwise or with the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_or` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_or`].
- pub fn atomic_or_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_or_acquire<T: Copy>(dst: *mut T, src: T) -> T;
/// Bitwise or with the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_or` method by passing
/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_or`].
- pub fn atomic_or_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_or_release<T: Copy>(dst: *mut T, src: T) -> T;
/// Bitwise or with the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_xor` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_xor`].
- pub fn atomic_xor<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xor_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
/// Bitwise xor with the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_xor` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_xor`].
- pub fn atomic_xor_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xor_acquire<T: Copy>(dst: *mut T, src: T) -> T;
/// Bitwise xor with the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `fetch_xor` method by passing
/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_xor`].
- pub fn atomic_xor_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xor_release<T: Copy>(dst: *mut T, src: T) -> T;
/// Bitwise xor with the current value, returning the previous value.
///
/// The stabilized version of this intrinsic is available on the
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] signed integer types via the `fetch_max` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_max`].
- pub fn atomic_max<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_max_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
/// Maximum with the current value using a signed comparison.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] signed integer types via the `fetch_max` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_max`].
- pub fn atomic_max_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_max_acquire<T: Copy>(dst: *mut T, src: T) -> T;
/// Maximum with the current value using a signed comparison.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] signed integer types via the `fetch_max` method by passing
/// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_max`].
- pub fn atomic_max_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_max_release<T: Copy>(dst: *mut T, src: T) -> T;
/// Maximum with the current value using a signed comparison.
///
/// The stabilized version of this intrinsic is available on the
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] signed integer types via the `fetch_min` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_min`].
- pub fn atomic_min<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_min_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
/// Minimum with the current value using a signed comparison.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] signed integer types via the `fetch_min` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_min`].
- pub fn atomic_min_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_min_acquire<T: Copy>(dst: *mut T, src: T) -> T;
/// Minimum with the current value using a signed comparison.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] signed integer types via the `fetch_min` method by passing
/// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_min`].
- pub fn atomic_min_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_min_release<T: Copy>(dst: *mut T, src: T) -> T;
/// Minimum with the current value using a signed comparison.
///
/// The stabilized version of this intrinsic is available on the
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] unsigned integer types via the `fetch_min` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_min`].
- pub fn atomic_umin<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umin_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
/// Minimum with the current value using an unsigned comparison.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] unsigned integer types via the `fetch_min` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_min`].
- pub fn atomic_umin_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umin_acquire<T: Copy>(dst: *mut T, src: T) -> T;
/// Minimum with the current value using an unsigned comparison.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] unsigned integer types via the `fetch_min` method by passing
/// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_min`].
- pub fn atomic_umin_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umin_release<T: Copy>(dst: *mut T, src: T) -> T;
/// Minimum with the current value using an unsigned comparison.
///
/// The stabilized version of this intrinsic is available on the
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] unsigned integer types via the `fetch_max` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_max`].
- pub fn atomic_umax<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umax_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
/// Maximum with the current value using an unsigned comparison.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] unsigned integer types via the `fetch_max` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_max`].
- pub fn atomic_umax_acq<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umax_acquire<T: Copy>(dst: *mut T, src: T) -> T;
/// Maximum with the current value using an unsigned comparison.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] unsigned integer types via the `fetch_max` method by passing
/// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_max`].
- pub fn atomic_umax_rel<T: Copy>(dst: *mut T, src: T) -> T;
+ pub fn atomic_umax_release<T: Copy>(dst: *mut T, src: T) -> T;
/// Maximum with the current value using an unsigned comparison.
///
/// The stabilized version of this intrinsic is available on the
/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_max`].
pub fn atomic_umax_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
- /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
- /// if supported; otherwise, it is a no-op.
- /// Prefetches have no effect on the behavior of the program but can change its performance
- /// characteristics.
- ///
- /// The `locality` argument must be a constant integer and is a temporal locality specifier
- /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
- ///
- /// This intrinsic does not have a stable counterpart.
- pub fn prefetch_read_data<T>(data: *const T, locality: i32);
- /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
- /// if supported; otherwise, it is a no-op.
- /// Prefetches have no effect on the behavior of the program but can change its performance
- /// characteristics.
- ///
- /// The `locality` argument must be a constant integer and is a temporal locality specifier
- /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
- ///
- /// This intrinsic does not have a stable counterpart.
- pub fn prefetch_write_data<T>(data: *const T, locality: i32);
- /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
- /// if supported; otherwise, it is a no-op.
- /// Prefetches have no effect on the behavior of the program but can change its performance
- /// characteristics.
- ///
- /// The `locality` argument must be a constant integer and is a temporal locality specifier
- /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
- ///
- /// This intrinsic does not have a stable counterpart.
- pub fn prefetch_read_instruction<T>(data: *const T, locality: i32);
- /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
- /// if supported; otherwise, it is a no-op.
- /// Prefetches have no effect on the behavior of the program but can change its performance
- /// characteristics.
- ///
- /// The `locality` argument must be a constant integer and is a temporal locality specifier
- /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
- ///
- /// This intrinsic does not have a stable counterpart.
- pub fn prefetch_write_instruction<T>(data: *const T, locality: i32);
-}
-
-extern "rust-intrinsic" {
/// An atomic fence.
///
/// The stabilized version of this intrinsic is available in
/// [`atomic::fence`] by passing [`Ordering::SeqCst`]
/// as the `order`.
- pub fn atomic_fence();
+ pub fn atomic_fence_seqcst();
/// An atomic fence.
///
/// The stabilized version of this intrinsic is available in
/// [`atomic::fence`] by passing [`Ordering::Acquire`]
/// as the `order`.
- pub fn atomic_fence_acq();
+ pub fn atomic_fence_acquire();
/// An atomic fence.
///
/// The stabilized version of this intrinsic is available in
/// [`atomic::fence`] by passing [`Ordering::Release`]
/// as the `order`.
- pub fn atomic_fence_rel();
+ pub fn atomic_fence_release();
/// An atomic fence.
///
/// The stabilized version of this intrinsic is available in
/// The stabilized version of this intrinsic is available in
/// [`atomic::compiler_fence`] by passing [`Ordering::SeqCst`]
/// as the `order`.
- pub fn atomic_singlethreadfence();
+ pub fn atomic_singlethreadfence_seqcst();
/// A compiler-only memory barrier.
///
/// Memory accesses will never be reordered across this barrier by the
/// The stabilized version of this intrinsic is available in
/// [`atomic::compiler_fence`] by passing [`Ordering::Acquire`]
/// as the `order`.
- pub fn atomic_singlethreadfence_acq();
+ pub fn atomic_singlethreadfence_acquire();
/// A compiler-only memory barrier.
///
/// Memory accesses will never be reordered across this barrier by the
/// The stabilized version of this intrinsic is available in
/// [`atomic::compiler_fence`] by passing [`Ordering::Release`]
/// as the `order`.
- pub fn atomic_singlethreadfence_rel();
+ pub fn atomic_singlethreadfence_release();
/// A compiler-only memory barrier.
///
/// Memory accesses will never be reordered across this barrier by the
/// [`atomic::compiler_fence`] by passing [`Ordering::AcqRel`]
/// as the `order`.
pub fn atomic_singlethreadfence_acqrel();
+}
+
+// These have been renamed.
+//
+// These are the aliases for the old names.
+// To be removed when stdarch and panic_unwind have been updated.
+#[cfg(not(bootstrap))]
+mod atomics {
+ pub use super::atomic_cxchg_acqrel_acquire as atomic_cxchg_acqrel;
+ pub use super::atomic_cxchg_acqrel_relaxed as atomic_cxchg_acqrel_failrelaxed;
+ pub use super::atomic_cxchg_acquire_acquire as atomic_cxchg_acq;
+ pub use super::atomic_cxchg_acquire_relaxed as atomic_cxchg_acq_failrelaxed;
+ pub use super::atomic_cxchg_relaxed_relaxed as atomic_cxchg_relaxed;
+ pub use super::atomic_cxchg_release_relaxed as atomic_cxchg_rel;
+ pub use super::atomic_cxchg_seqcst_acquire as atomic_cxchg_failacq;
+ pub use super::atomic_cxchg_seqcst_relaxed as atomic_cxchg_failrelaxed;
+ pub use super::atomic_cxchg_seqcst_seqcst as atomic_cxchg;
+ pub use super::atomic_store_seqcst as atomic_store;
+}
+
+#[cfg(not(bootstrap))]
+pub use atomics::*;
+
+extern "rust-intrinsic" {
+ /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+ /// if supported; otherwise, it is a no-op.
+ /// Prefetches have no effect on the behavior of the program but can change its performance
+ /// characteristics.
+ ///
+ /// The `locality` argument must be a constant integer and is a temporal locality specifier
+ /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
+ ///
+ /// This intrinsic does not have a stable counterpart.
+ pub fn prefetch_read_data<T>(data: *const T, locality: i32);
+ /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+ /// if supported; otherwise, it is a no-op.
+ /// Prefetches have no effect on the behavior of the program but can change its performance
+ /// characteristics.
+ ///
+ /// The `locality` argument must be a constant integer and is a temporal locality specifier
+ /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
+ ///
+ /// This intrinsic does not have a stable counterpart.
+ pub fn prefetch_write_data<T>(data: *const T, locality: i32);
+ /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+ /// if supported; otherwise, it is a no-op.
+ /// Prefetches have no effect on the behavior of the program but can change its performance
+ /// characteristics.
+ ///
+ /// The `locality` argument must be a constant integer and is a temporal locality specifier
+ /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
+ ///
+ /// This intrinsic does not have a stable counterpart.
+ pub fn prefetch_read_instruction<T>(data: *const T, locality: i32);
+ /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+ /// if supported; otherwise, it is a no-op.
+ /// Prefetches have no effect on the behavior of the program but can change its performance
+ /// characteristics.
+ ///
+ /// The `locality` argument must be a constant integer and is a temporal locality specifier
+ /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
+ ///
+ /// This intrinsic does not have a stable counterpart.
+ pub fn prefetch_write_instruction<T>(data: *const T, locality: i32);
/// Magic intrinsic that derives its meaning from attributes
/// attached to the function.
unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 }
}
+ /// Logical "not" with a boolean value.
+ ///
+ /// Performs a logical "not" operation on the current value, and sets
+ /// the new value to the result.
+ ///
+ /// Returns the previous value.
+ ///
+ /// `fetch_not` takes an [`Ordering`] argument which describes the memory ordering
+ /// of this operation. All ordering modes are possible. Note that using
+ /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
+ /// using [`Release`] makes the load part [`Relaxed`].
+ ///
+ /// **Note:** This method is only available on platforms that support atomic
+ /// operations on `u8`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(atomic_bool_fetch_not)]
+ /// use std::sync::atomic::{AtomicBool, Ordering};
+ ///
+ /// let foo = AtomicBool::new(true);
+ /// assert_eq!(foo.fetch_not(Ordering::SeqCst), true);
+ /// assert_eq!(foo.load(Ordering::SeqCst), false);
+ ///
+ /// let foo = AtomicBool::new(false);
+ /// assert_eq!(foo.fetch_not(Ordering::SeqCst), false);
+ /// assert_eq!(foo.load(Ordering::SeqCst), true);
+ /// ```
+ #[inline]
+ #[unstable(feature = "atomic_bool_fetch_not", issue = "98485")]
+ #[cfg(target_has_atomic = "8")]
+ pub fn fetch_not(&self, order: Ordering) -> bool {
+ self.fetch_xor(true, order)
+ }
+
/// Returns a mutable pointer to the underlying [`bool`].
///
/// Doing non-atomic reads and writes on the resulting integer can be a data race.
// SAFETY: the caller must uphold the safety contract for `atomic_store`.
unsafe {
match order {
- Release => intrinsics::atomic_store_rel(dst, val),
Relaxed => intrinsics::atomic_store_relaxed(dst, val),
- SeqCst => intrinsics::atomic_store(dst, val),
+ Release => intrinsics::atomic_store_release(dst, val),
+ SeqCst => intrinsics::atomic_store_seqcst(dst, val),
Acquire => panic!("there is no such thing as an acquire store"),
- AcqRel => panic!("there is no such thing as an acquire/release store"),
+ AcqRel => panic!("there is no such thing as an acquire-release store"),
}
}
}
// SAFETY: the caller must uphold the safety contract for `atomic_load`.
unsafe {
match order {
- Acquire => intrinsics::atomic_load_acq(dst),
Relaxed => intrinsics::atomic_load_relaxed(dst),
- SeqCst => intrinsics::atomic_load(dst),
+ Acquire => intrinsics::atomic_load_acquire(dst),
+ SeqCst => intrinsics::atomic_load_seqcst(dst),
Release => panic!("there is no such thing as a release load"),
- AcqRel => panic!("there is no such thing as an acquire/release load"),
+ AcqRel => panic!("there is no such thing as an acquire-release load"),
}
}
}
// SAFETY: the caller must uphold the safety contract for `atomic_swap`.
unsafe {
match order {
- Acquire => intrinsics::atomic_xchg_acq(dst, val),
- Release => intrinsics::atomic_xchg_rel(dst, val),
- AcqRel => intrinsics::atomic_xchg_acqrel(dst, val),
Relaxed => intrinsics::atomic_xchg_relaxed(dst, val),
- SeqCst => intrinsics::atomic_xchg(dst, val),
+ Acquire => intrinsics::atomic_xchg_acquire(dst, val),
+ Release => intrinsics::atomic_xchg_release(dst, val),
+ AcqRel => intrinsics::atomic_xchg_acqrel(dst, val),
+ SeqCst => intrinsics::atomic_xchg_seqcst(dst, val),
}
}
}
// SAFETY: the caller must uphold the safety contract for `atomic_add`.
unsafe {
match order {
- Acquire => intrinsics::atomic_xadd_acq(dst, val),
- Release => intrinsics::atomic_xadd_rel(dst, val),
- AcqRel => intrinsics::atomic_xadd_acqrel(dst, val),
Relaxed => intrinsics::atomic_xadd_relaxed(dst, val),
- SeqCst => intrinsics::atomic_xadd(dst, val),
+ Acquire => intrinsics::atomic_xadd_acquire(dst, val),
+ Release => intrinsics::atomic_xadd_release(dst, val),
+ AcqRel => intrinsics::atomic_xadd_acqrel(dst, val),
+ SeqCst => intrinsics::atomic_xadd_seqcst(dst, val),
}
}
}
// SAFETY: the caller must uphold the safety contract for `atomic_sub`.
unsafe {
match order {
- Acquire => intrinsics::atomic_xsub_acq(dst, val),
- Release => intrinsics::atomic_xsub_rel(dst, val),
- AcqRel => intrinsics::atomic_xsub_acqrel(dst, val),
Relaxed => intrinsics::atomic_xsub_relaxed(dst, val),
- SeqCst => intrinsics::atomic_xsub(dst, val),
+ Acquire => intrinsics::atomic_xsub_acquire(dst, val),
+ Release => intrinsics::atomic_xsub_release(dst, val),
+ AcqRel => intrinsics::atomic_xsub_acqrel(dst, val),
+ SeqCst => intrinsics::atomic_xsub_seqcst(dst, val),
}
}
}
// SAFETY: the caller must uphold the safety contract for `atomic_compare_exchange`.
let (val, ok) = unsafe {
match (success, failure) {
- (Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new),
- (Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new),
- (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new),
- (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new),
- (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new),
- (Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new),
- (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new),
- (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new),
- (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new),
- (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
+ (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed_relaxed(dst, old, new),
+ //(Relaxed, Acquire) => intrinsics::atomic_cxchg_relaxed_acquire(dst, old, new),
+ //(Relaxed, SeqCst) => intrinsics::atomic_cxchg_relaxed_seqcst(dst, old, new),
+ (Acquire, Relaxed) => intrinsics::atomic_cxchg_acquire_relaxed(dst, old, new),
+ (Acquire, Acquire) => intrinsics::atomic_cxchg_acquire_acquire(dst, old, new),
+ //(Acquire, SeqCst) => intrinsics::atomic_cxchg_acquire_seqcst(dst, old, new),
+ (Release, Relaxed) => intrinsics::atomic_cxchg_release_relaxed(dst, old, new),
+ //(Release, Acquire) => intrinsics::atomic_cxchg_release_acquire(dst, old, new),
+ //(Release, SeqCst) => intrinsics::atomic_cxchg_release_seqcst(dst, old, new),
+ (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_relaxed(dst, old, new),
+ (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel_acquire(dst, old, new),
+ //(AcqRel, SeqCst) => intrinsics::atomic_cxchg_acqrel_seqcst(dst, old, new),
+ (SeqCst, Relaxed) => intrinsics::atomic_cxchg_seqcst_relaxed(dst, old, new),
+ (SeqCst, Acquire) => intrinsics::atomic_cxchg_seqcst_acquire(dst, old, new),
+ (SeqCst, SeqCst) => intrinsics::atomic_cxchg_seqcst_seqcst(dst, old, new),
+ (_, AcqRel) => panic!("there is no such thing as an acquire-release failure ordering"),
(_, Release) => panic!("there is no such thing as a release failure ordering"),
_ => panic!("a failure ordering can't be stronger than a success ordering"),
}
// SAFETY: the caller must uphold the safety contract for `atomic_compare_exchange_weak`.
let (val, ok) = unsafe {
match (success, failure) {
- (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new),
- (Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new),
- (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new),
- (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed(dst, old, new),
- (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak(dst, old, new),
- (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acq_failrelaxed(dst, old, new),
- (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new),
- (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new),
- (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new),
- (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
+ (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed_relaxed(dst, old, new),
+ //(Relaxed, Acquire) => intrinsics::atomic_cxchgweak_relaxed_acquire(dst, old, new),
+ //(Relaxed, SeqCst) => intrinsics::atomic_cxchgweak_relaxed_seqcst(dst, old, new),
+ (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acquire_relaxed(dst, old, new),
+ (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acquire_acquire(dst, old, new),
+ //(Acquire, SeqCst) => intrinsics::atomic_cxchgweak_acquire_seqcst(dst, old, new),
+ (Release, Relaxed) => intrinsics::atomic_cxchgweak_release_relaxed(dst, old, new),
+ //(Release, Acquire) => intrinsics::atomic_cxchgweak_release_acquire(dst, old, new),
+ //(Release, SeqCst) => intrinsics::atomic_cxchgweak_release_seqcst(dst, old, new),
+ (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_relaxed(dst, old, new),
+ (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel_acquire(dst, old, new),
+ //(AcqRel, SeqCst) => intrinsics::atomic_cxchgweak_acqrel_seqcst(dst, old, new),
+ (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_seqcst_relaxed(dst, old, new),
+ (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_seqcst_acquire(dst, old, new),
+ (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak_seqcst_seqcst(dst, old, new),
+ (_, AcqRel) => panic!("there is no such thing as an acquire-release failure ordering"),
(_, Release) => panic!("there is no such thing as a release failure ordering"),
_ => panic!("a failure ordering can't be stronger than a success ordering"),
}
// SAFETY: the caller must uphold the safety contract for `atomic_and`
unsafe {
match order {
- Acquire => intrinsics::atomic_and_acq(dst, val),
- Release => intrinsics::atomic_and_rel(dst, val),
- AcqRel => intrinsics::atomic_and_acqrel(dst, val),
Relaxed => intrinsics::atomic_and_relaxed(dst, val),
- SeqCst => intrinsics::atomic_and(dst, val),
+ Acquire => intrinsics::atomic_and_acquire(dst, val),
+ Release => intrinsics::atomic_and_release(dst, val),
+ AcqRel => intrinsics::atomic_and_acqrel(dst, val),
+ SeqCst => intrinsics::atomic_and_seqcst(dst, val),
}
}
}
// SAFETY: the caller must uphold the safety contract for `atomic_nand`
unsafe {
match order {
- Acquire => intrinsics::atomic_nand_acq(dst, val),
- Release => intrinsics::atomic_nand_rel(dst, val),
- AcqRel => intrinsics::atomic_nand_acqrel(dst, val),
Relaxed => intrinsics::atomic_nand_relaxed(dst, val),
- SeqCst => intrinsics::atomic_nand(dst, val),
+ Acquire => intrinsics::atomic_nand_acquire(dst, val),
+ Release => intrinsics::atomic_nand_release(dst, val),
+ AcqRel => intrinsics::atomic_nand_acqrel(dst, val),
+ SeqCst => intrinsics::atomic_nand_seqcst(dst, val),
}
}
}
// SAFETY: the caller must uphold the safety contract for `atomic_or`
unsafe {
match order {
- Acquire => intrinsics::atomic_or_acq(dst, val),
- Release => intrinsics::atomic_or_rel(dst, val),
+ SeqCst => intrinsics::atomic_or_seqcst(dst, val),
+ Acquire => intrinsics::atomic_or_acquire(dst, val),
+ Release => intrinsics::atomic_or_release(dst, val),
AcqRel => intrinsics::atomic_or_acqrel(dst, val),
Relaxed => intrinsics::atomic_or_relaxed(dst, val),
- SeqCst => intrinsics::atomic_or(dst, val),
}
}
}
// SAFETY: the caller must uphold the safety contract for `atomic_xor`
unsafe {
match order {
- Acquire => intrinsics::atomic_xor_acq(dst, val),
- Release => intrinsics::atomic_xor_rel(dst, val),
+ SeqCst => intrinsics::atomic_xor_seqcst(dst, val),
+ Acquire => intrinsics::atomic_xor_acquire(dst, val),
+ Release => intrinsics::atomic_xor_release(dst, val),
AcqRel => intrinsics::atomic_xor_acqrel(dst, val),
Relaxed => intrinsics::atomic_xor_relaxed(dst, val),
- SeqCst => intrinsics::atomic_xor(dst, val),
}
}
}
// SAFETY: the caller must uphold the safety contract for `atomic_max`
unsafe {
match order {
- Acquire => intrinsics::atomic_max_acq(dst, val),
- Release => intrinsics::atomic_max_rel(dst, val),
- AcqRel => intrinsics::atomic_max_acqrel(dst, val),
Relaxed => intrinsics::atomic_max_relaxed(dst, val),
- SeqCst => intrinsics::atomic_max(dst, val),
+ Acquire => intrinsics::atomic_max_acquire(dst, val),
+ Release => intrinsics::atomic_max_release(dst, val),
+ AcqRel => intrinsics::atomic_max_acqrel(dst, val),
+ SeqCst => intrinsics::atomic_max_seqcst(dst, val),
}
}
}
// SAFETY: the caller must uphold the safety contract for `atomic_min`
unsafe {
match order {
- Acquire => intrinsics::atomic_min_acq(dst, val),
- Release => intrinsics::atomic_min_rel(dst, val),
- AcqRel => intrinsics::atomic_min_acqrel(dst, val),
Relaxed => intrinsics::atomic_min_relaxed(dst, val),
- SeqCst => intrinsics::atomic_min(dst, val),
+ Acquire => intrinsics::atomic_min_acquire(dst, val),
+ Release => intrinsics::atomic_min_release(dst, val),
+ AcqRel => intrinsics::atomic_min_acqrel(dst, val),
+ SeqCst => intrinsics::atomic_min_seqcst(dst, val),
}
}
}
// SAFETY: the caller must uphold the safety contract for `atomic_umax`
unsafe {
match order {
- Acquire => intrinsics::atomic_umax_acq(dst, val),
- Release => intrinsics::atomic_umax_rel(dst, val),
- AcqRel => intrinsics::atomic_umax_acqrel(dst, val),
Relaxed => intrinsics::atomic_umax_relaxed(dst, val),
- SeqCst => intrinsics::atomic_umax(dst, val),
+ Acquire => intrinsics::atomic_umax_acquire(dst, val),
+ Release => intrinsics::atomic_umax_release(dst, val),
+ AcqRel => intrinsics::atomic_umax_acqrel(dst, val),
+ SeqCst => intrinsics::atomic_umax_seqcst(dst, val),
}
}
}
// SAFETY: the caller must uphold the safety contract for `atomic_umin`
unsafe {
match order {
- Acquire => intrinsics::atomic_umin_acq(dst, val),
- Release => intrinsics::atomic_umin_rel(dst, val),
- AcqRel => intrinsics::atomic_umin_acqrel(dst, val),
Relaxed => intrinsics::atomic_umin_relaxed(dst, val),
- SeqCst => intrinsics::atomic_umin(dst, val),
+ Acquire => intrinsics::atomic_umin_acquire(dst, val),
+ Release => intrinsics::atomic_umin_release(dst, val),
+ AcqRel => intrinsics::atomic_umin_acqrel(dst, val),
+ SeqCst => intrinsics::atomic_umin_seqcst(dst, val),
}
}
}
// SAFETY: using an atomic fence is safe.
unsafe {
match order {
- Acquire => intrinsics::atomic_fence_acq(),
- Release => intrinsics::atomic_fence_rel(),
+ Acquire => intrinsics::atomic_fence_acquire(),
+ Release => intrinsics::atomic_fence_release(),
AcqRel => intrinsics::atomic_fence_acqrel(),
- SeqCst => intrinsics::atomic_fence(),
+ SeqCst => intrinsics::atomic_fence_seqcst(),
Relaxed => panic!("there is no such thing as a relaxed fence"),
}
}
// SAFETY: using an atomic fence is safe.
unsafe {
match order {
- Acquire => intrinsics::atomic_singlethreadfence_acq(),
- Release => intrinsics::atomic_singlethreadfence_rel(),
+ Acquire => intrinsics::atomic_singlethreadfence_acquire(),
+ Release => intrinsics::atomic_singlethreadfence_release(),
AcqRel => intrinsics::atomic_singlethreadfence_acqrel(),
- SeqCst => intrinsics::atomic_singlethreadfence(),
+ SeqCst => intrinsics::atomic_singlethreadfence_seqcst(),
Relaxed => panic!("there is no such thing as a relaxed compiler fence"),
}
}
}
}
+fn new_cc_build(build: &Build, target: TargetSelection) -> cc::Build {
+ let mut cfg = cc::Build::new();
+ cfg.cargo_metadata(false)
+ .opt_level(2)
+ .warnings(false)
+ .debug(false)
+ .target(&target.triple)
+ .host(&build.build.triple);
+ match build.crt_static(target) {
+ Some(a) => {
+ cfg.static_crt(a);
+ }
+ None => {
+ if target.contains("msvc") {
+ cfg.static_crt(true);
+ }
+ if target.contains("musl") {
+ cfg.static_flag(true);
+ }
+ }
+ }
+ cfg
+}
+
pub fn find(build: &mut Build) {
// For all targets we're going to need a C compiler for building some shims
// and such as well as for being a linker for Rust code.
.chain(iter::once(build.build))
.collect::<HashSet<_>>();
for target in targets.into_iter() {
- let mut cfg = cc::Build::new();
- cfg.cargo_metadata(false)
- .opt_level(2)
- .warnings(false)
- .debug(false)
- .target(&target.triple)
- .host(&build.build.triple);
- match build.crt_static(target) {
- Some(a) => {
- cfg.static_crt(a);
- }
- None => {
- if target.contains("msvc") {
- cfg.static_crt(true);
- }
- if target.contains("musl") {
- cfg.static_flag(true);
- }
- }
- }
-
+ let mut cfg = new_cc_build(build, target);
let config = build.config.target_config.get(&target);
if let Some(cc) = config.and_then(|c| c.cc.as_ref()) {
cfg.compiler(cc);
// If we use llvm-libunwind, we will need a C++ compiler as well for all targets
// We'll need one anyways if the target triple is also a host triple
- let mut cfg = cc::Build::new();
- cfg.cargo_metadata(false)
- .opt_level(2)
- .warnings(false)
- .debug(false)
- .cpp(true)
- .target(&target.triple)
- .host(&build.build.triple);
-
+ let mut cfg = new_cc_build(build, target);
+ cfg.cpp(true);
let cxx_configured = if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
cfg.compiler(cxx);
true
minifier = "0.2.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
-smallvec = "1.6.1"
+smallvec = "1.8.1"
tempfile = "3"
itertools = "0.10.1"
regex = "1"
window.hidePopoverMenus();
}
- const disableShortcuts = getSettingValue("disable-shortcuts") === "true";
function handleShortcut(ev) {
// Don't interfere with browser shortcuts
+ const disableShortcuts = getSettingValue("disable-shortcuts") === "true";
if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) {
return;
}
- if (document.activeElement.tagName === "INPUT") {
+ if (document.activeElement.tagName === "INPUT" &&
+ document.activeElement.type !== "checkbox") {
switch (getVirtualKey(ev)) {
case "Escape":
handleEscape(ev);
function showHelp() {
const menu = getHelpMenu(true);
if (menu.style.display === "none") {
+ window.hidePopoverMenus();
menu.style.display = "";
}
}
const shouldShowHelp = menu.style.display === "none";
if (shouldShowHelp) {
showHelp();
+ } else {
+ window.hidePopoverMenus();
}
});
_18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_13 = (move _14, move _18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ Retag(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_20); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_34 = Option::<Arguments>::None; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ Retag(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_28 = core::panicking::assert_failed::<usize, usize>(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-include ../tools.mk
all:
- $(RUSTC) --edition=2021 --crate-type=rlib ../../../../library/alloc/src/lib.rs --cfg no_global_oom_handling
+ $(RUSTC) --edition=2021 -Dwarnings --crate-type=rlib ../../../../library/alloc/src/lib.rs --cfg no_global_oom_handling
#![no_core]
extern "rust-intrinsic" {
- fn atomic_xadd<T>(dst: *mut T, src: T) -> T;
+ fn atomic_xadd_seqcst<T>(dst: *mut T, src: T) -> T;
}
#[lang = "sized"]
#[cfg(target_has_atomic = "8")]
pub unsafe fn atomic_u8(x: *mut u8) {
- atomic_xadd(x, 1);
- atomic_xadd(x, 1);
+ atomic_xadd_seqcst(x, 1);
+ atomic_xadd_seqcst(x, 1);
}
#[cfg(target_has_atomic = "8")]
pub unsafe fn atomic_i8(x: *mut i8) {
- atomic_xadd(x, 1);
+ atomic_xadd_seqcst(x, 1);
}
#[cfg(target_has_atomic = "16")]
pub unsafe fn atomic_u16(x: *mut u16) {
- atomic_xadd(x, 1);
+ atomic_xadd_seqcst(x, 1);
}
#[cfg(target_has_atomic = "16")]
pub unsafe fn atomic_i16(x: *mut i16) {
- atomic_xadd(x, 1);
+ atomic_xadd_seqcst(x, 1);
}
#[cfg(target_has_atomic = "32")]
pub unsafe fn atomic_u32(x: *mut u32) {
- atomic_xadd(x, 1);
+ atomic_xadd_seqcst(x, 1);
}
#[cfg(target_has_atomic = "32")]
pub unsafe fn atomic_i32(x: *mut i32) {
- atomic_xadd(x, 1);
+ atomic_xadd_seqcst(x, 1);
}
#[cfg(target_has_atomic = "64")]
pub unsafe fn atomic_u64(x: *mut u64) {
- atomic_xadd(x, 1);
+ atomic_xadd_seqcst(x, 1);
}
#[cfg(target_has_atomic = "64")]
pub unsafe fn atomic_i64(x: *mut i64) {
- atomic_xadd(x, 1);
+ atomic_xadd_seqcst(x, 1);
}
#[cfg(target_has_atomic = "128")]
pub unsafe fn atomic_u128(x: *mut u128) {
- atomic_xadd(x, 1);
+ atomic_xadd_seqcst(x, 1);
}
#[cfg(target_has_atomic = "128")]
pub unsafe fn atomic_i128(x: *mut i128) {
- atomic_xadd(x, 1);
+ atomic_xadd_seqcst(x, 1);
}
#[cfg(target_has_atomic = "ptr")]
pub unsafe fn atomic_usize(x: *mut usize) {
- atomic_xadd(x, 1);
+ atomic_xadd_seqcst(x, 1);
}
#[cfg(target_has_atomic = "ptr")]
pub unsafe fn atomic_isize(x: *mut isize) {
- atomic_xadd(x, 1);
+ atomic_xadd_seqcst(x, 1);
}
assert-css: ("#help-button .popover", {"display": "block"})
assert-css: ("#settings-menu .popover", {"display": "none"})
+// Now verify that clicking the help menu again closes it.
+click: "#help-button"
+assert-css: ("#help-button .popover", {"display": "none"})
+assert-css: ("#settings-menu .popover", {"display": "none"})
+
// We check the borders color now:
// Ayu theme
click: ".setting-line:last-child .toggle .label"
assert-local-storage: {"rustdoc-disable-shortcuts": "true"}
+// Make sure that "Disable keyboard shortcuts" actually took effect.
+press-key: "Escape"
+press-key: "?"
+assert-false: "#help-button .popover"
+wait-for-css: ("#settings-menu .popover", {"display": "block"})
+
+// Now turn keyboard shortcuts back on, and see if they work.
+click: ".setting-line:last-child .toggle .label"
+assert-local-storage: {"rustdoc-disable-shortcuts": "false"}
+press-key: "Escape"
+press-key: "?"
+wait-for-css: ("#help-button .popover", {"display": "block"})
+assert-css: ("#settings-menu .popover", {"display": "none"})
+
// Now we go to the settings page to check that the CSS is loaded as expected.
goto: file://|DOC_PATH|/settings.html
wait-for: "#settings"
--> $DIR/basic.rs:21:5
|
LL | extra("");
- | ^^^^^ -- argument unexpected
+ | ^^^^^ -- argument of type `&'static str` unexpected
|
note: function defined here
--> $DIR/basic.rs:14:4
--> $DIR/extra_arguments.rs:7:3
|
LL | empty("");
- | ^^^^^ -- argument unexpected
+ | ^^^^^ -- argument of type `&'static str` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:1:4
--> $DIR/extra_arguments.rs:9:3
|
LL | one_arg(1, 1);
- | ^^^^^^^ - argument unexpected
+ | ^^^^^^^ - argument of type `{integer}` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:2:4
--> $DIR/extra_arguments.rs:10:3
|
LL | one_arg(1, "");
- | ^^^^^^^ -- argument unexpected
+ | ^^^^^^^ -- argument of type `&'static str` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:2:4
--> $DIR/extra_arguments.rs:11:3
|
LL | one_arg(1, "", 1.0);
- | ^^^^^^^ -- --- argument unexpected
+ | ^^^^^^^ -- --- argument of type `{float}` unexpected
| |
- | argument unexpected
+ | argument of type `&'static str` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:2:4
--> $DIR/extra_arguments.rs:13:3
|
LL | two_arg_same(1, 1, 1);
- | ^^^^^^^^^^^^ - argument unexpected
+ | ^^^^^^^^^^^^ - argument of type `{integer}` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:3:4
--> $DIR/extra_arguments.rs:14:3
|
LL | two_arg_same(1, 1, 1.0);
- | ^^^^^^^^^^^^ --- argument unexpected
+ | ^^^^^^^^^^^^ --- argument of type `{float}` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:3:4
--> $DIR/extra_arguments.rs:16:3
|
LL | two_arg_diff(1, 1, "");
- | ^^^^^^^^^^^^ - argument of type `&str` unexpected
+ | ^^^^^^^^^^^^ - argument of type `{integer}` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:4:4
--> $DIR/extra_arguments.rs:17:3
|
LL | two_arg_diff(1, "", "");
- | ^^^^^^^^^^^^ -- argument unexpected
+ | ^^^^^^^^^^^^ -- argument of type `&'static str` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:4:4
--> $DIR/extra_arguments.rs:18:3
|
LL | two_arg_diff(1, 1, "", "");
- | ^^^^^^^^^^^^ - -- argument unexpected
+ | ^^^^^^^^^^^^ - -- argument of type `&'static str` unexpected
| |
- | argument of type `&str` unexpected
+ | argument of type `{integer}` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:4:4
--> $DIR/extra_arguments.rs:19:3
|
LL | two_arg_diff(1, "", 1, "");
- | ^^^^^^^^^^^^ - -- argument unexpected
+ | ^^^^^^^^^^^^ - -- argument of type `&'static str` unexpected
| |
- | argument unexpected
+ | argument of type `{integer}` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:4:4
--> $DIR/extra_arguments.rs:22:3
|
LL | two_arg_same(1, 1, "");
- | ^^^^^^^^^^^^ -- argument unexpected
+ | ^^^^^^^^^^^^ -- argument of type `&'static str` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:3:4
--> $DIR/extra_arguments.rs:23:3
|
LL | two_arg_diff(1, 1, "");
- | ^^^^^^^^^^^^ - argument of type `&str` unexpected
+ | ^^^^^^^^^^^^ - argument of type `{integer}` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:4:4
| ^^^^^^^^^^^^
...
LL | ""
- | -- argument unexpected
+ | -- argument of type `&'static str` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:3:4
| ^^^^^^^^^^^^
LL | 1,
LL | 1,
- | - argument of type `&str` unexpected
+ | - argument of type `{integer}` unexpected
|
note: function defined here
--> $DIR/extra_arguments.rs:4:4
--> $DIR/issue-97484.rs:12:5
|
LL | foo(&&A, B, C, D, E, F, G);
- | ^^^ - - - argument unexpected
+ | ^^^ - - - argument of type `F` unexpected
| | |
- | | argument of type `&E` unexpected
- | argument of type `D` unexpected
+ | | argument of type `C` unexpected
+ | argument of type `B` unexpected
|
note: function defined here
--> $DIR/issue-97484.rs:9:4
|
LL | fn foo(a: &A, d: D, e: &E, g: G) {}
| ^^^ ----- ---- ----- ----
-help: consider removing the ``
- |
-LL - foo(&&A, B, C, D, E, F, G);
-LL + foo(&&A, B, C, D, E, F, G);
+help: consider borrowing here
|
+LL | foo(&&A, B, C, D, &E, F, G);
+ | ~~
help: remove the extra arguments
|
LL | foo(&&A, D, /* &E */, G);
--> $DIR/mixed_cases.rs:10:3
|
LL | two_args(1, "", X {});
- | ^^^^^^^^ -- ---- argument unexpected
+ | ^^^^^^^^ -- ---- argument of type `X` unexpected
| |
| expected `f32`, found `&str`
|
--> $DIR/mixed_cases.rs:11:3
|
LL | three_args(1, "", X {}, "");
- | ^^^^^^^^^^ -- ---- -- argument unexpected
+ | ^^^^^^^^^^ -- ---- -- argument of type `&'static str` unexpected
| | |
- | | argument of type `&str` unexpected
+ | | argument of type `X` unexpected
| an argument of type `f32` is missing
|
note: function defined here
--> $DIR/mixed_cases.rs:17:3
|
LL | three_args(1, "", X {});
- | ^^^^^^^^^^ -- ---- argument of type `&str` unexpected
+ | ^^^^^^^^^^ -- ---- argument of type `X` unexpected
| |
| an argument of type `f32` is missing
|
LL | Box::new(AssocNoCopy)
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
- = note: required for the cast to the object type `dyn Bar<Assoc = <AssocNoCopy as Thing>::Out::{opaque#0}>`
+ = note: required for the cast from `AssocNoCopy` to the object type `dyn Bar<Assoc = <AssocNoCopy as Thing>::Out::{opaque#0}>`
error: aborting due to previous error
|
LL | type A = usize;
| ^^^^^
- = note: required for the cast to the object type `dyn Foo<A = Bar>`
+ = note: required for the cast from `isize` to the object type `dyn Foo<A = Bar>`
error: aborting due to 3 previous errors
LL | let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
| ^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
- = note: required for the cast to the object type `dyn Iterator<Item = u32, Item = i32>`
+ = note: required for the cast from `std::vec::IntoIter<u32>` to the object type `dyn Iterator<Item = u32, Item = i32>`
error: aborting due to previous error
|
LL | impl<'a, T: MyDisplay> MyDisplay for &'a mut T { }
| ^^^^^^^^^ ^^^^^^^^^
- = note: required for the cast to the object type `dyn MyDisplay`
+ = note: required for the cast from `&mut T` to the object type `dyn MyDisplay`
error: aborting due to 2 previous errors
| ^^^^^^ the trait `MyDisplay` is not implemented for `T`
|
= help: the trait `MyDisplay` is implemented for `&'a mut T`
- = note: required for the cast to the object type `dyn MyDisplay`
+ = note: required for the cast from `T` to the object type `dyn MyDisplay`
error: aborting due to 2 previous errors
LL | let _: &dyn Future<Output = ()> = █
| ^^^^^^ expected `()`, found `u8`
|
- = note: required for the cast to the object type `dyn Future<Output = ()>`
+ = note: required for the cast from `impl Future<Output = u8>` to the object type `dyn Future<Output = ()>`
error[E0308]: mismatched types
--> $DIR/async-block-control-flow-static-semantics.rs:12:43
LL | let _: &dyn Future<Output = ()> = █
| ^^^^^^ expected `()`, found `u8`
|
- = note: required for the cast to the object type `dyn Future<Output = ()>`
+ = note: required for the cast from `impl Future<Output = u8>` to the object type `dyn Future<Output = ()>`
error[E0308]: mismatched types
--> $DIR/async-block-control-flow-static-semantics.rs:47:44
|
LL | let x = x;
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
- = note: required for the cast to the object type `dyn Future<Output = ()> + Send`
+ = note: required for the cast from `impl Future<Output = ()>` to the object type `dyn Future<Output = ()> + Send`
help: consider further restricting this bound
|
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
error[E0507]: cannot move out of `*m` which is behind a mutable reference
--> $DIR/binop-move-semantics.rs:30:5
|
-LL | *m
- | ^^ move occurs because `*m` has type `T`, which does not implement the `Copy` trait
+LL | *m
+ | -^
+ | |
+ | _____move occurs because `*m` has type `T`, which does not implement the `Copy` trait
+ | |
+LL | | +
+LL | | *n;
+ | |______- `*m` moved due to usage in operator
+ |
+note: calling this operator moves the left-hand side
+ --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
+ |
+LL | fn add(self, rhs: Rhs) -> Self::Output;
+ | ^^^^
error[E0507]: cannot move out of `*n` which is behind a shared reference
--> $DIR/binop-move-semantics.rs:32:5
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5
|
LL | let t1 = t0;
- | -- help: consider changing this to be a mutable reference: `&mut &mut isize`
+ | -- consider changing this binding's type to be: `&mut &mut isize`
LL | let p: &isize = &**t0;
LL | **t1 = 22;
| ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written
fn main() {
let mut test = Vec::new();
let rofl: &Vec<Vec<i32>> = &mut test;
- //~^ HELP consider changing this to be a mutable reference
+ //~^ NOTE consider changing this binding's type to be
rofl.push(Vec::new());
//~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
//~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
#[rustfmt::skip]
let x: &usize = &mut{0};
- //~^ HELP consider changing this to be a mutable reference
+ //~^ NOTE consider changing this binding's type to be
*x = 1;
//~^ ERROR cannot assign to `*x`, which is behind a `&` reference
//~| NOTE `x` is a `&` reference, so the data it refers to cannot be written
#[rustfmt::skip]
let y: &usize = &mut(0);
- //~^ HELP consider changing this to be a mutable reference
+ //~^ NOTE consider changing this binding's type to be
*y = 1;
//~^ ERROR cannot assign to `*y`, which is behind a `&` reference
//~| NOTE `y` is a `&` reference, so the data it refers to cannot be written
--> $DIR/issue-85765.rs:5:5
|
LL | let rofl: &Vec<Vec<i32>> = &mut test;
- | ---- help: consider changing this to be a mutable reference: `&mut Vec<Vec<i32>>`
+ | ---- consider changing this binding's type to be: `&mut Vec<Vec<i32>>`
LL |
LL | rofl.push(Vec::new());
| ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
--> $DIR/issue-85765.rs:19:5
|
LL | let x: &usize = &mut{0};
- | - help: consider changing this to be a mutable reference: `&mut usize`
+ | - consider changing this binding's type to be: `&mut usize`
LL |
LL | *x = 1;
| ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
--> $DIR/issue-85765.rs:26:5
|
LL | let y: &usize = &mut(0);
- | - help: consider changing this to be a mutable reference: `&mut usize`
+ | - consider changing this binding's type to be: `&mut usize`
LL |
LL | *y = 1;
| ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written
fn main() {
let client = TestClient;
let inner = client.get_inner_ref();
- //~^ HELP consider changing this to be a mutable reference
+ //~^ NOTE consider changing this binding's type to be
inner.clear();
//~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596]
+ //~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
}
--> $DIR/issue-91206.rs:13:5
|
LL | let inner = client.get_inner_ref();
- | ----- help: consider changing this to be a mutable reference: `&mut Vec<usize>`
+ | ----- consider changing this binding's type to be: `&mut Vec<usize>`
LL |
LL | inner.clear();
| ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
--> $DIR/issue-92015.rs:6:5
|
LL | let foo = Some(&0).unwrap();
- | --- help: consider changing this to be a mutable reference: `&mut i32`
+ | --- consider changing this binding's type to be: `&mut i32`
LL | *foo = 1;
| ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
--- /dev/null
+// This is not exactly right, yet.
+
+// Ideally we should be suggesting `as_mut` for the first case,
+// and suggesting to change `as_ref` to `as_mut` in the second.
+
+fn x(cb: &mut Option<&mut dyn FnMut()>) {
+ cb.map(|cb| cb());
+ //~^ ERROR cannot move out of `*cb` which is behind a mutable reference
+}
+
+fn x2(cb: &mut Option<&mut dyn FnMut()>) {
+ cb.as_ref().map(|cb| cb());
+ //~^ ERROR cannot borrow `*cb` as mutable, as it is behind a `&` reference
+}
+
+fn main() {}
--- /dev/null
+error[E0507]: cannot move out of `*cb` which is behind a mutable reference
+ --> $DIR/suggest-as-ref-on-mut-closure.rs:7:5
+ |
+LL | cb.map(|cb| cb());
+ | ^^^--------------
+ | | |
+ | | `*cb` moved due to this method call
+ | move occurs because `*cb` has type `Option<&mut dyn FnMut()>`, which does not implement the `Copy` trait
+ |
+note: this function takes ownership of the receiver `self`, which moves `*cb`
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ |
+LL | pub const fn map<U, F>(self, f: F) -> Option<U>
+ | ^^^^
+help: consider calling `.as_ref()` to borrow the type's contents
+ |
+LL | cb.as_ref().map(|cb| cb());
+ | +++++++++
+
+error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
+ --> $DIR/suggest-as-ref-on-mut-closure.rs:12:26
+ |
+LL | cb.as_ref().map(|cb| cb());
+ | -- ^^ `cb` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+ | |
+ | consider changing this binding's type to be: `&mut &mut dyn FnMut()`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0507, E0596.
+For more information about an error, try `rustc --explain E0507`.
LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
|
- = note: required for the cast to the object type `dyn std::error::Error`
+ = note: required for the cast from `()` to the object type `dyn std::error::Error`
error[E0277]: the trait bound `(): std::error::Error` is not satisfied
--> $DIR/coerce-issue-49593-box-never-windows.rs:23:49
LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
|
- = note: required for the cast to the object type `(dyn std::error::Error + 'static)`
+ = note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)`
error: aborting due to 2 previous errors
LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
|
- = note: required for the cast to the object type `dyn std::error::Error`
+ = note: required for the cast from `()` to the object type `dyn std::error::Error`
error[E0277]: the trait bound `(): std::error::Error` is not satisfied
--> $DIR/coerce-issue-49593-box-never.rs:23:49
LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
|
- = note: required for the cast to the object type `(dyn std::error::Error + 'static)`
+ = note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)`
error: aborting due to 2 previous errors
| required by a bound introduced by this call
|
= help: the trait `Trait<2_u8>` is implemented for `u32`
- = note: required for the cast to the object type `dyn Trait`
+ = note: required for the cast from `u32` to the object type `dyn Trait`
error[E0277]: the trait bound `bool: Traitor<{_: u8}>` is not satisfied
--> $DIR/trait_objects_fail.rs:28:9
| required by a bound introduced by this call
|
= help: the trait `Traitor<2_u8, 3_u8>` is implemented for `bool`
- = note: required for the cast to the object type `dyn Traitor<{_: u8}>`
+ = note: required for the cast from `bool` to the object type `dyn Traitor<{_: u8}>`
error: aborting due to 2 previous errors
--- /dev/null
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
+
+#[derive(Debug, PartialEq, Eq)]
+struct Foo {
+ value: i32,
+ nested: &'static Bar<i32>,
+}
+
+#[derive(Debug, PartialEq, Eq)]
+struct Bar<T>(T);
+
+struct Test<const F: Foo>;
+
+fn main() {
+ let x: Test<{
+ Foo {
+ value: 3,
+ nested: &Bar(4),
+ }
+ }> = Test;
+ let y: Test<{
+ Foo {
+ value: 3,
+ nested: &Bar(5),
+ }
+ }> = x; //~ ERROR mismatched types
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-66451.rs:27:10
+ |
+LL | let y: Test<{
+ | ____________-
+LL | | Foo {
+LL | | value: 3,
+LL | | nested: &Bar(5),
+LL | | }
+LL | | }> = x;
+ | | - ^ expected `Foo { value: 3_i32, nested: &Bar::<i32>(5_i32) }`, found `Foo { value: 3_i32, nested: &Bar::<i32>(4_i32) }`
+ | |______|
+ | expected due to this
+ |
+ = note: expected struct `Test<Foo { value: 3_i32, nested: &Bar::<i32>(5_i32) }>`
+ found struct `Test<Foo { value: 3_i32, nested: &Bar::<i32>(4_i32) }>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// check-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Num<const N: usize>;
+
+trait NumT {
+ const VALUE: usize;
+}
+
+impl<const N: usize> NumT for Num<N> {
+ const VALUE: usize = N;
+}
+
+struct Foo<'a, N: NumT>(&'a [u32; N::VALUE]) where [(); N::VALUE]:;
+
+trait Bar {
+ type Size: NumT;
+
+ fn bar<'a>(foo: &Foo<'a, Self::Size>) where [(); Self::Size::VALUE]: {
+ todo!();
+ }
+}
+
+trait Baz<'a> {
+ type Size: NumT;
+
+ fn baz(foo: &Foo<'a, Self::Size>) where [(); Self::Size::VALUE]: {
+ todo!();
+ }
+}
+
+fn main() {}
LL | fn wrong_kind(){}
| ^^^^^^^^^^^^^^^^^ the trait `Testable` is not implemented for `TestDescAndFn`
|
- = note: required for the cast to the object type `dyn Testable`
+ = note: required for the cast from `TestDescAndFn` to the object type `dyn Testable`
= note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
LL | let f3: &Fat<dyn Bar> = f2;
| ^^ the trait `Bar` is not implemented for `Foo`
|
- = note: required for the cast to the object type `dyn Bar`
+ = note: required for the cast from `Foo` to the object type `dyn Bar`
error[E0308]: mismatched types
--> $DIR/dst-bad-coerce1.rs:28:27
LL | let f3: &(dyn Bar,) = f2;
| ^^ the trait `Bar` is not implemented for `Foo`
|
- = note: required for the cast to the object type `dyn Bar`
+ = note: required for the cast from `Foo` to the object type `dyn Bar`
error: aborting due to 4 previous errors
-error[E0161]: cannot move a value of type str: the size of str cannot be statically determined
+error[E0161]: cannot move a value of type `str`
--> $DIR/dst-index.rs:31:5
|
LL | S[0];
- | ^^^^
+ | ^^^^ the size of `str` cannot be statically determined
-error[E0161]: cannot move a value of type dyn Debug: the size of dyn Debug cannot be statically determined
+error[E0161]: cannot move a value of type `dyn Debug`
--> $DIR/dst-index.rs:34:5
|
LL | T[0];
- | ^^^^
+ | ^^^^ the size of `dyn Debug` cannot be statically determined
error[E0507]: cannot move out of index of `S`
--> $DIR/dst-index.rs:31:5
LL | let u: &dyn Foo = t;
| ^ doesn't have a size known at compile-time
|
- = note: required for the cast to the object type `dyn Foo`
+ = note: required for the cast from `T` to the object type `dyn Foo`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn test1<T: ?Sized + Foo>(t: &T) {
LL | let v: &dyn Foo = t as &dyn Foo;
| ^ doesn't have a size known at compile-time
|
- = note: required for the cast to the object type `dyn Foo`
+ = note: required for the cast from `T` to the object type `dyn Foo`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn test2<T: ?Sized + Foo>(t: &T) {
| ^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
- = note: required for the cast to the object type `dyn Foo`
+ = note: required for the cast from `str` to the object type `dyn Foo`
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/dst-object-from-unsized-type.rs:23:23
| ^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
- = note: required for the cast to the object type `dyn Foo`
+ = note: required for the cast from `[u8]` to the object type `dyn Foo`
error: aborting due to 4 previous errors
--> $DIR/E0057.rs:5:13
|
LL | let c = f(2, 3);
- | ^ - argument unexpected
+ | ^ - argument of type `{integer}` unexpected
|
note: closure defined here
--> $DIR/E0057.rs:2:13
-error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
+error[E0161]: cannot move a value of type `dyn Bar`
--> $DIR/E0161.rs:16:5
|
LL | x.f();
- | ^^^^^
+ | ^^^^^ the size of `dyn Bar` cannot be statically determined
error: aborting due to previous error
| ^^^^^
= note: expected trait object `(dyn RefCont<'_, u8> + 'static)`
found reference `&u8`
- = note: required for the cast to the object type `dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>`
+ = note: required for the cast from `BTreeMap<u8, u8>` to the object type `dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>`
error: aborting due to 2 previous errors
LL | v.t(|| {});
| ^^^^^^^^^^
|
- = note: could not prove [closure@$DIR/issue-59311.rs:17:9: 17:14] well-formed
+ = note: could not prove `[closure@$DIR/issue-59311.rs:17:9: 17:14] well-formed`
error: higher-ranked lifetime error
--> $DIR/issue-59311.rs:17:9
LL | v.t(|| {});
| ^^^^^
|
- = note: could not prove for<'a> &'a V: 'static
+ = note: could not prove `for<'a> &'a V: 'static`
error: aborting due to 2 previous errors
pub mod rusti {
extern "rust-intrinsic" {
- pub fn atomic_xchg<T>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xchg_seqcst<T>(dst: *mut T, src: T) -> T;
}
}
#[inline(always)]
-pub fn atomic_xchg(dst: *mut isize, src: isize) -> isize {
+pub fn atomic_xchg_seqcst(dst: *mut isize, src: isize) -> isize {
unsafe {
- rusti::atomic_xchg(dst, src)
+ rusti::atomic_xchg_seqcst(dst, src)
}
}
extern crate cci_intrinsic;
-use cci_intrinsic::atomic_xchg;
+use cci_intrinsic::atomic_xchg_seqcst;
pub fn main() {
let mut x = 1;
- atomic_xchg(&mut x, 5);
+ atomic_xchg_seqcst(&mut x, 5);
assert_eq!(x, 5);
}
mod rusti {
extern "rust-intrinsic" {
- pub fn atomic_cxchg<T>(dst: *mut T, old: T, src: T) -> (T, bool);
- pub fn atomic_cxchg_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
- pub fn atomic_cxchg_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_seqcst_seqcst<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_acquire_acquire<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchg_release_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
- pub fn atomic_cxchgweak<T>(dst: *mut T, old: T, src: T) -> (T, bool);
- pub fn atomic_cxchgweak_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
- pub fn atomic_cxchgweak_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_seqcst_seqcst<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_acquire_acquire<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+ pub fn atomic_cxchgweak_release_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
- pub fn atomic_load<T>(src: *const T) -> T;
- pub fn atomic_load_acq<T>(src: *const T) -> T;
+ pub fn atomic_load_seqcst<T>(src: *const T) -> T;
+ pub fn atomic_load_acquire<T>(src: *const T) -> T;
- pub fn atomic_store<T>(dst: *mut T, val: T);
- pub fn atomic_store_rel<T>(dst: *mut T, val: T);
+ pub fn atomic_store_seqcst<T>(dst: *mut T, val: T);
+ pub fn atomic_store_release<T>(dst: *mut T, val: T);
- pub fn atomic_xchg<T>(dst: *mut T, src: T) -> T;
- pub fn atomic_xchg_acq<T>(dst: *mut T, src: T) -> T;
- pub fn atomic_xchg_rel<T>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xchg_seqcst<T>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xchg_acquire<T>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xchg_release<T>(dst: *mut T, src: T) -> T;
- pub fn atomic_xadd<T>(dst: *mut T, src: T) -> T;
- pub fn atomic_xadd_acq<T>(dst: *mut T, src: T) -> T;
- pub fn atomic_xadd_rel<T>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xadd_seqcst<T>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xadd_acquire<T>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xadd_release<T>(dst: *mut T, src: T) -> T;
- pub fn atomic_xsub<T>(dst: *mut T, src: T) -> T;
- pub fn atomic_xsub_acq<T>(dst: *mut T, src: T) -> T;
- pub fn atomic_xsub_rel<T>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xsub_seqcst<T>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xsub_acquire<T>(dst: *mut T, src: T) -> T;
+ pub fn atomic_xsub_release<T>(dst: *mut T, src: T) -> T;
}
}
unsafe {
let mut x: Box<_> = Box::new(1);
- assert_eq!(rusti::atomic_load(&*x), 1);
+ assert_eq!(rusti::atomic_load_seqcst(&*x), 1);
*x = 5;
- assert_eq!(rusti::atomic_load_acq(&*x), 5);
+ assert_eq!(rusti::atomic_load_acquire(&*x), 5);
- rusti::atomic_store(&mut *x,3);
+ rusti::atomic_store_seqcst(&mut *x,3);
assert_eq!(*x, 3);
- rusti::atomic_store_rel(&mut *x,1);
+ rusti::atomic_store_release(&mut *x,1);
assert_eq!(*x, 1);
- assert_eq!(rusti::atomic_cxchg(&mut *x, 1, 2), (1, true));
+ assert_eq!(rusti::atomic_cxchg_seqcst_seqcst(&mut *x, 1, 2), (1, true));
assert_eq!(*x, 2);
- assert_eq!(rusti::atomic_cxchg_acq(&mut *x, 1, 3), (2, false));
+ assert_eq!(rusti::atomic_cxchg_acquire_acquire(&mut *x, 1, 3), (2, false));
assert_eq!(*x, 2);
- assert_eq!(rusti::atomic_cxchg_rel(&mut *x, 2, 1), (2, true));
+ assert_eq!(rusti::atomic_cxchg_release_relaxed(&mut *x, 2, 1), (2, true));
assert_eq!(*x, 1);
- assert_eq!(rusti::atomic_xchg(&mut *x, 0), 1);
+ assert_eq!(rusti::atomic_xchg_seqcst(&mut *x, 0), 1);
assert_eq!(*x, 0);
- assert_eq!(rusti::atomic_xchg_acq(&mut *x, 1), 0);
+ assert_eq!(rusti::atomic_xchg_acquire(&mut *x, 1), 0);
assert_eq!(*x, 1);
- assert_eq!(rusti::atomic_xchg_rel(&mut *x, 0), 1);
+ assert_eq!(rusti::atomic_xchg_release(&mut *x, 0), 1);
assert_eq!(*x, 0);
- assert_eq!(rusti::atomic_xadd(&mut *x, 1), 0);
- assert_eq!(rusti::atomic_xadd_acq(&mut *x, 1), 1);
- assert_eq!(rusti::atomic_xadd_rel(&mut *x, 1), 2);
+ assert_eq!(rusti::atomic_xadd_seqcst(&mut *x, 1), 0);
+ assert_eq!(rusti::atomic_xadd_acquire(&mut *x, 1), 1);
+ assert_eq!(rusti::atomic_xadd_release(&mut *x, 1), 2);
assert_eq!(*x, 3);
- assert_eq!(rusti::atomic_xsub(&mut *x, 1), 3);
- assert_eq!(rusti::atomic_xsub_acq(&mut *x, 1), 2);
- assert_eq!(rusti::atomic_xsub_rel(&mut *x, 1), 1);
+ assert_eq!(rusti::atomic_xsub_seqcst(&mut *x, 1), 3);
+ assert_eq!(rusti::atomic_xsub_acquire(&mut *x, 1), 2);
+ assert_eq!(rusti::atomic_xsub_release(&mut *x, 1), 1);
assert_eq!(*x, 0);
loop {
- let res = rusti::atomic_cxchgweak(&mut *x, 0, 1);
+ let res = rusti::atomic_cxchgweak_seqcst_seqcst(&mut *x, 0, 1);
assert_eq!(res.0, 0);
if res.1 {
break;
assert_eq!(*x, 1);
loop {
- let res = rusti::atomic_cxchgweak_acq(&mut *x, 1, 2);
+ let res = rusti::atomic_cxchgweak_acquire_acquire(&mut *x, 1, 2);
assert_eq!(res.0, 1);
if res.1 {
break;
assert_eq!(*x, 2);
loop {
- let res = rusti::atomic_cxchgweak_rel(&mut *x, 2, 3);
+ let res = rusti::atomic_cxchgweak_release_relaxed(&mut *x, 2, 3);
assert_eq!(res.0, 2);
if res.1 {
break;
pub type Quux = [u8; 100];
pub unsafe fn test_bool_load(p: &mut bool, v: bool) {
- intrinsics::atomic_load(p);
- //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
+ intrinsics::atomic_load_seqcst(p);
+ //~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `bool`
}
pub unsafe fn test_bool_store(p: &mut bool, v: bool) {
- intrinsics::atomic_store(p, v);
- //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool`
+ intrinsics::atomic_store_seqcst(p, v);
+ //~^ ERROR `atomic_store_seqcst` intrinsic: expected basic integer type, found `bool`
}
pub unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
- intrinsics::atomic_xchg(p, v);
- //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool`
+ intrinsics::atomic_xchg_seqcst(p, v);
+ //~^ ERROR `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `bool`
}
pub unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
- intrinsics::atomic_cxchg(p, v, v);
- //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
+ intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+ //~^ ERROR `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `bool`
}
pub unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
- intrinsics::atomic_load(p);
- //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
+ intrinsics::atomic_load_seqcst(p);
+ //~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `Foo`
}
pub unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
- intrinsics::atomic_store(p, v);
- //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo`
+ intrinsics::atomic_store_seqcst(p, v);
+ //~^ ERROR `atomic_store_seqcst` intrinsic: expected basic integer type, found `Foo`
}
pub unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
- intrinsics::atomic_xchg(p, v);
- //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
+ intrinsics::atomic_xchg_seqcst(p, v);
+ //~^ ERROR `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `Foo`
}
pub unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
- intrinsics::atomic_cxchg(p, v, v);
- //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
+ intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+ //~^ ERROR `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `Foo`
}
pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
- intrinsics::atomic_load(p);
+ intrinsics::atomic_load_seqcst(p);
//~^ ERROR expected basic integer type, found `&dyn Fn()`
}
pub unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
- intrinsics::atomic_store(p, v);
+ intrinsics::atomic_store_seqcst(p, v);
//~^ ERROR expected basic integer type, found `&dyn Fn()`
}
pub unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
- intrinsics::atomic_xchg(p, v);
+ intrinsics::atomic_xchg_seqcst(p, v);
//~^ ERROR expected basic integer type, found `&dyn Fn()`
}
pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
- intrinsics::atomic_cxchg(p, v, v);
+ intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
//~^ ERROR expected basic integer type, found `&dyn Fn()`
}
pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
- intrinsics::atomic_load(p);
- //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
+ intrinsics::atomic_load_seqcst(p);
+ //~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
}
pub unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
- intrinsics::atomic_store(p, v);
- //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
+ intrinsics::atomic_store_seqcst(p, v);
+ //~^ ERROR `atomic_store_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
}
pub unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
- intrinsics::atomic_xchg(p, v);
- //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
+ intrinsics::atomic_xchg_seqcst(p, v);
+ //~^ ERROR `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
}
pub unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
- intrinsics::atomic_cxchg(p, v, v);
- //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
+ intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+ //~^ ERROR `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
}
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `bool`
--> $DIR/non-integer-atomic.rs:15:5
|
-LL | intrinsics::atomic_load(p);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_load_seqcst(p);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `bool`
--> $DIR/non-integer-atomic.rs:20:5
|
-LL | intrinsics::atomic_store(p, v);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_store_seqcst(p, v);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `bool`
--> $DIR/non-integer-atomic.rs:25:5
|
-LL | intrinsics::atomic_xchg(p, v);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_xchg_seqcst(p, v);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `bool`
--> $DIR/non-integer-atomic.rs:30:5
|
-LL | intrinsics::atomic_cxchg(p, v, v);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `Foo`
--> $DIR/non-integer-atomic.rs:35:5
|
-LL | intrinsics::atomic_load(p);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_load_seqcst(p);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `Foo`
--> $DIR/non-integer-atomic.rs:40:5
|
-LL | intrinsics::atomic_store(p, v);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_store_seqcst(p, v);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `Foo`
--> $DIR/non-integer-atomic.rs:45:5
|
-LL | intrinsics::atomic_xchg(p, v);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_xchg_seqcst(p, v);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `Foo`
--> $DIR/non-integer-atomic.rs:50:5
|
-LL | intrinsics::atomic_cxchg(p, v, v);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()`
--> $DIR/non-integer-atomic.rs:55:5
|
-LL | intrinsics::atomic_load(p);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_load_seqcst(p);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()`
--> $DIR/non-integer-atomic.rs:60:5
|
-LL | intrinsics::atomic_store(p, v);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_store_seqcst(p, v);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()`
--> $DIR/non-integer-atomic.rs:65:5
|
-LL | intrinsics::atomic_xchg(p, v);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_xchg_seqcst(p, v);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()`
--> $DIR/non-integer-atomic.rs:70:5
|
-LL | intrinsics::atomic_cxchg(p, v, v);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
--> $DIR/non-integer-atomic.rs:75:5
|
-LL | intrinsics::atomic_load(p);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_load_seqcst(p);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
--> $DIR/non-integer-atomic.rs:80:5
|
-LL | intrinsics::atomic_store(p, v);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_store_seqcst(p, v);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
--> $DIR/non-integer-atomic.rs:85:5
|
-LL | intrinsics::atomic_xchg(p, v);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_xchg_seqcst(p, v);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
--> $DIR/non-integer-atomic.rs:90:5
|
-LL | intrinsics::atomic_cxchg(p, v, v);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 16 previous errors
| ^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
- = note: required for the cast to the object type `dyn Any`
+ = note: required for the cast from `str` to the object type `dyn Any`
help: consider borrowing the value, since `&str` can be coerced into `dyn Any`
|
LL | let _x = &"test" as &dyn (::std::any::Any);
|
= help: the trait `Fn<()>` is not implemented for `()`
= note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
- = note: required for the cast to the object type `dyn Fn()`
+ = note: required for the cast from `()` to the object type `dyn Fn()`
error: aborting due to previous error
|
LL | impl<'b, P> Wrap<'b> for Wrapper<P>
| ^^^^^^^^ ^^^^^^^^^^
- = note: required for the cast to the object type `dyn for<'b> Wrap<'b>`
+ = note: required for the cast from `Wrapper<P>` to the object type `dyn for<'b> Wrap<'b>`
help: consider further restricting the associated type
|
LL | fn push_process<P>(process: P) where P: Process<'static>, <P as Process<'_>>::Item: Iterator {
macro_rules! some_macro {
($other: expr) => ({
- $other(None) //~ NOTE argument unexpected
+ $other(None) //~ NOTE argument of type `Option<_>` unexpected
})
}
--> $DIR/issue-26094.rs:10:17
|
LL | $other(None)
- | ---- argument unexpected
+ | ---- argument of type `Option<_>` unexpected
...
LL | some_macro!(some_function);
| ^^^^^^^^^^^^^
--> $DIR/issue-4935.rs:5:13
|
LL | fn main() { foo(5, 6) }
- | ^^^ - argument unexpected
+ | ^^^ - argument of type `{integer}` unexpected
|
note: function defined here
--> $DIR/issue-4935.rs:3:4
*foo = 32;
//~^ ERROR cannot assign to `*foo`, which is behind a `&` reference
let bar = foo;
- //~^ HELP consider changing this to be a mutable reference
- //~| SUGGESTION &mut i32
*bar = 64;
//~^ ERROR cannot assign to `*bar`, which is behind a `&` reference
}
| ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
- --> $DIR/issue-51515.rs:10:5
+ --> $DIR/issue-51515.rs:8:5
|
LL | let bar = foo;
- | --- help: consider changing this to be a mutable reference: `&mut i32`
-...
+ | --- consider changing this binding's type to be: `&mut i32`
LL | *bar = 64;
| ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
|
LL | struct B {
| ^
- = note: required for the cast to the object type `dyn Foo + Send`
+ = note: required for the cast from `B` to the object type `dyn Foo + Send`
error: aborting due to previous error
|
LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
| ^^^^^^^^^^^ ^^^^
- = note: required for the cast to the object type `dyn Gettable<T>`
+ = note: required for the cast from `S<T>` to the object type `dyn Gettable<T>`
help: consider restricting type parameter `T`
|
LL | fn f<T: std::marker::Send>(val: T) {
|
LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
| ^^^^^^^^^^^ ^^^^
- = note: required for the cast to the object type `dyn Gettable<T>`
+ = note: required for the cast from `S<T>` to the object type `dyn Gettable<T>`
help: consider restricting type parameter `T`
|
LL | fn f<T: std::marker::Copy>(val: T) {
|
LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
| ^^^^^^^^^^^ ^^^^
- = note: required for the cast to the object type `dyn Gettable<T>`
+ = note: required for the cast from `S<T>` to the object type `dyn Gettable<T>`
help: consider restricting type parameter `T`
|
LL | fn g<T: std::marker::Send>(val: T) {
|
LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
| ^^^^^^^^^^^ ^^^^
- = note: required for the cast to the object type `dyn Gettable<T>`
+ = note: required for the cast from `S<T>` to the object type `dyn Gettable<T>`
help: consider restricting type parameter `T`
|
LL | fn g<T: std::marker::Copy>(val: T) {
|
LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
| ^^^^^^^^^^^ ^^^^
- = note: required for the cast to the object type `dyn Gettable<String>`
+ = note: required for the cast from `S<String>` to the object type `dyn Gettable<String>`
error[E0277]: the trait bound `Foo: Copy` is not satisfied
--> $DIR/kindck-impl-type-params.rs:43:37
|
LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
| ^^^^^^^^^^^ ^^^^
- = note: required for the cast to the object type `dyn Gettable<Foo>`
+ = note: required for the cast from `S<Foo>` to the object type `dyn Gettable<Foo>`
help: consider annotating `Foo` with `#[derive(Copy)]`
|
LL | #[derive(Copy)]
LL | foo(&10);
| ^^^^^^^^
|
- = note: could not prove for<'b, 'r> &'b (): 'r
+ = note: could not prove `for<'b, 'r> &'b (): 'r`
error: aborting due to previous error
--> $DIR/method-call-err-msg.rs:13:7
|
LL | x.zero(0)
- | ^^^^ - argument unexpected
+ | ^^^^ - argument of type `{integer}` unexpected
|
note: associated function defined here
--> $DIR/method-call-err-msg.rs:5:8
struct Bug {
A: [(); { *"" }.len()],
- //~^ ERROR: cannot move a value of type str
+ //~^ ERROR: cannot move a value of type `str`
//~| ERROR: cannot move out of a shared reference
}
-error[E0161]: cannot move a value of type str: the size of str cannot be statically determined
+error[E0161]: cannot move a value of type `str`
--> $DIR/issue-67947.rs:2:13
|
LL | A: [(); { *"" }.len()],
- | ^^^^^^^
+ | ^^^^^^^ the size of `str` cannot be statically determined
error[E0507]: cannot move out of a shared reference
--> $DIR/issue-67947.rs:2:15
| ^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
- = note: required for the cast to the object type `dyn Foo`
+ = note: required for the cast from `[u8]` to the object type `dyn Foo`
help: consider borrowing the value, since `&[u8]` can be coerced into `dyn Foo`
|
LL | let _ = &fat_v as *const dyn Foo;
| ^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
- = note: required for the cast to the object type `dyn Foo`
+ = note: required for the cast from `str` to the object type `dyn Foo`
help: consider borrowing the value, since `&str` can be coerced into `dyn Foo`
|
LL | let _ = &a as *const dyn Foo;
--> $DIR/overloaded-calls-bad.rs:31:15
|
LL | let ans = s("burma", "shave");
- | ^ ------- ------- argument unexpected
+ | ^ ------- ------- argument of type `&'static str` unexpected
| |
| expected `isize`, found `&str`
|
|
= note: expected unit type `()`
found type `!`
- = note: required for the cast to the object type `dyn FnMut()`
+ = note: required for the cast from `[closure@$DIR/fallback-closure-wrap.rs:18:40: 21:6]` to the object type `dyn FnMut()`
error: aborting due to previous error
}
fn use_bar(t: Box<dyn Bar>) {
- t.bar() //~ ERROR cannot move a value of type dyn Bar
+ t.bar() //~ ERROR cannot move a value of type `dyn Bar`
}
fn main() { }
-error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
+error[E0161]: cannot move a value of type `dyn Bar`
--> $DIR/object-safety-by-value-self-use.rs:15:5
|
LL | t.bar()
- | ^^^^^^^
+ | ^^^^^^^ the size of `dyn Bar` cannot be statically determined
error: aborting due to previous error
// aux-build:invalid-punct-ident.rs
-// rustc-env:RUST_BACKTRACE=0
-
-// FIXME https://github.com/rust-lang/rust/issues/59998
-// normalize-stderr-test "thread.*panicked.*proc_macro.*lib.rs.*\n" -> ""
-// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
-// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
-// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
-// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
-// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
-// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
-// normalize-stderr-test "query stack during panic:\n" -> ""
-// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> ""
-// normalize-stderr-test "end of query stack\n" -> ""
+// ignore-stage1
+// only-linux
+//
+// FIXME: This should be a normal (stage1, all platforms) test in
+// src/test/ui/proc-macro once issue #59998 is fixed.
#[macro_use]
extern crate invalid_punct_ident;
error: proc macro panicked
- --> $DIR/invalid-punct-ident-1.rs:19:1
+ --> $DIR/invalid-punct-ident-1.rs:11:1
|
LL | invalid_punct!();
| ^^^^^^^^^^^^^^^^
LL | |
LL | | loop {}
LL | | }
- | | ^
- | | |
- | |_call the function in a closure: `|| unsafe { /* code */ }`
- | required by a bound introduced by this call
+ | |_^ call the function in a closure: `|| unsafe { /* code */ }`
|
= help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
= note: unsafe function cannot be called generically without an unsafe block
--> $DIR/issue-34264.rs:7:5
|
LL | foo(Some(42), 2, "");
- | ^^^ -- argument unexpected
+ | ^^^ -- argument of type `&'static str` unexpected
|
note: function defined here
--> $DIR/issue-34264.rs:1:4
--> $DIR/issue-34264.rs:10:5
|
LL | bar(1, 2, 3);
- | ^^^ - argument unexpected
+ | ^^^ - argument of type `{integer}` unexpected
|
note: function defined here
--> $DIR/issue-34264.rs:3:4
--- /dev/null
+#![feature(min_specialization)]
+use std::fmt::{self, Display};
+
+pub enum Cow<'a, B: ?Sized + 'a, O = <B as ToOwned>::Owned>
+where
+ B: ToOwned,
+{
+ Borrowed(&'a B),
+ Owned(O),
+}
+
+impl ToString for Cow<'_, str> {
+ fn to_string(&self) -> String {
+ String::new()
+ }
+}
+
+impl<B: ?Sized> Display for Cow<'_, B> { //~ ERROR: the trait bound `B: Clone` is not satisfied [E0277]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { //~ ERROR: the trait bound `B: Clone` is not satisfied [E0277]
+ write!(f, "foo")
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0277]: the trait bound `B: Clone` is not satisfied
+ --> $DIR/issue-79224.rs:18:17
+ |
+LL | impl<B: ?Sized> Display for Cow<'_, B> {
+ | ^^^^^^^ the trait `Clone` is not implemented for `B`
+ |
+ = note: required because of the requirements on the impl of `ToOwned` for `B`
+help: consider further restricting this bound
+ |
+LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
+ | +++++++++++++++++++
+
+error[E0277]: the trait bound `B: Clone` is not satisfied
+ --> $DIR/issue-79224.rs:19:5
+ |
+LL | / fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+LL | | write!(f, "foo")
+LL | | }
+ | |_____^ the trait `Clone` is not implemented for `B`
+ |
+ = note: required because of the requirements on the impl of `ToOwned` for `B`
+help: consider further restricting this bound
+ |
+LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
+ | +++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
--> $DIR/args-instead-of-tuple-errors.rs:6:34
|
LL | let _: Option<(i32, bool)> = Some(1, 2);
- | ^^^^ - - argument unexpected
+ | ^^^^ - - argument of type `{integer}` unexpected
| |
| expected tuple, found integer
|
--> $DIR/args-instead-of-tuple-errors.rs:8:5
|
LL | int_bool(1, 2);
- | ^^^^^^^^ - - argument unexpected
+ | ^^^^^^^^ - - argument of type `{integer}` unexpected
| |
| expected tuple, found integer
|
|
LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
| ^^
-help: use parentheses to construct a tuple
+help: wrap these arguments in parentheses to construct a tuple
|
LL | let _: Result<(i32, i8), ()> = Ok((1, 2));
| + +
|
LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
| ^^^^
-help: use parentheses to construct a tuple
+help: wrap these arguments in parentheses to construct a tuple
|
LL | let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi"));
| + +
|
LL | fn two_ints(_: (i32, i32)) {
| ^^^^^^^^ -------------
-help: use parentheses to construct a tuple
+help: wrap these arguments in parentheses to construct a tuple
|
LL | two_ints((1, 2));
| + +
|
LL | fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
| ^^^^^^^^^^^^ ----------------
-help: use parentheses to construct a tuple
+help: wrap these arguments in parentheses to construct a tuple
|
LL | with_generic((3, 4));
| + +
|
LL | fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
| ^^^^^^^^^^^^ ----------------
-help: use parentheses to construct a tuple
+help: wrap these arguments in parentheses to construct a tuple
|
LL | with_generic((a, b));
| + +
| ^^^^^ ^^^^^^^^
= note: 1 redundant requirement hidden
= note: required because of the requirements on the impl of `Debug` for `&c::Inner<T>`
- = note: required for the cast to the object type `dyn Debug`
+ = note: required for the cast from `&c::Inner<T>` to the object type `dyn Debug`
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `T`
|
| ^^^^^ ^^^^^^^^
= note: 1 redundant requirement hidden
= note: required because of the requirements on the impl of `Debug` for `&d::Inner<T>`
- = note: required for the cast to the object type `dyn Debug`
+ = note: required for the cast from `&d::Inner<T>` to the object type `dyn Debug`
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `T`
|
| ^^^^^ ^^^^^^^^
= note: 1 redundant requirement hidden
= note: required because of the requirements on the impl of `Debug` for `&e::Inner<T>`
- = note: required for the cast to the object type `dyn Debug`
+ = note: required for the cast from `&e::Inner<T>` to the object type `dyn Debug`
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `T`
|
| ^^^^^ ^^^^^^^^
= note: 1 redundant requirement hidden
= note: required because of the requirements on the impl of `Debug` for `&f::Inner<T>`
- = note: required for the cast to the object type `dyn Debug`
+ = note: required for the cast from `&f::Inner<T>` to the object type `dyn Debug`
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `T`
|
--> $DIR/option-content-move.rs:11:20
|
LL | if selection.1.unwrap().contains(selection.0) {
- | ^^^^^^^^^^^ move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
+ | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
+ | |
+ | move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
|
-help: consider borrowing the `Option`'s content
+note: this function takes ownership of the receiver `self`, which moves `selection.1`
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ |
+LL | pub const fn unwrap(self) -> T {
+ | ^^^^
+help: consider calling `.as_ref()` to borrow the type's contents
|
LL | if selection.1.as_ref().unwrap().contains(selection.0) {
- | +++++++++
+ | +++++++++
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
--> $DIR/option-content-move.rs:29:20
|
LL | if selection.1.unwrap().contains(selection.0) {
- | ^^^^^^^^^^^ move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
+ | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
+ | |
+ | move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
+ |
+note: this function takes ownership of the receiver `self`, which moves `selection.1`
+ --> $SRC_DIR/core/src/result.rs:LL:COL
|
-help: consider borrowing the `Result`'s content
+LL | pub fn unwrap(self) -> T
+ | ^^^^
+help: consider calling `.as_ref()` to borrow the type's contents
|
LL | if selection.1.as_ref().unwrap().contains(selection.0) {
- | +++++++++
+ | +++++++++
error: aborting due to 2 previous errors
--- /dev/null
+use std::ffi::{OsStr, OsString};
+use std::path::Path;
+
+fn check(p: &dyn AsRef<Path>) {
+ let m = std::fs::metadata(&p);
+ println!("{:?}", &m);
+}
+
+fn main() {
+ let s: OsString = ".".into();
+ let s: &OsStr = &s;
+ check(s);
+ //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+ //~| HELP within `OsStr`, the trait `Sized` is not implemented for `[u8]`
+ //~| HELP consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef<Path>`
+}
--- /dev/null
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/suggest-borrow-to-dyn-object.rs:12:11
+ |
+LL | check(s);
+ | ----- ^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: within `OsStr`, the trait `Sized` is not implemented for `[u8]`
+ = note: required because it appears within the type `OsStr`
+ = note: required for the cast from `OsStr` to the object type `dyn AsRef<Path>`
+help: consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef<Path>`
+ |
+LL | check(&s);
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<isize>` is not implemented for `Struct`
|
= help: the trait `Trait<&'static str>` is implemented for `Struct`
- = note: required for the cast to the object type `dyn Trait<isize>`
+ = note: required for the cast from `Struct` to the object type `dyn Trait<isize>`
error: aborting due to previous error
| ^^^^^^^^^^^ the trait `Map<usize, isize>` is not implemented for `Box<dyn Map<isize, isize>>`
|
= help: the trait `Map<K, V>` is implemented for `HashMap<K, V>`
- = note: required for the cast to the object type `dyn Map<usize, isize>`
+ = note: required for the cast from `Box<dyn Map<isize, isize>>` to the object type `dyn Map<usize, isize>`
error: aborting due to previous error
LL | let _ = x as &dyn Bar<_>; // Ambiguous
| ^ the trait `Bar<_>` is not implemented for `&dyn Foo`
|
- = note: required for the cast to the object type `dyn Bar<_>`
+ = note: required for the cast from `&dyn Foo` to the object type `dyn Bar<_>`
error: aborting due to 2 previous errors
LL | let _ = x as &dyn Bar<u32>; // Error
| ^ the trait `Bar<u32>` is not implemented for `&dyn Foo<i32>`
|
- = note: required for the cast to the object type `dyn Bar<u32>`
+ = note: required for the cast from `&dyn Foo<i32>` to the object type `dyn Bar<u32>`
error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>`
--> $DIR/type-checking-test-2.rs:26:13
LL | let a = x as &dyn Bar<_>; // Ambiguous
| ^ the trait `Bar<_>` is not implemented for `&dyn Foo<u32>`
|
- = note: required for the cast to the object type `dyn Bar<_>`
+ = note: required for the cast from `&dyn Foo<u32>` to the object type `dyn Bar<_>`
error: aborting due to 4 previous errors
--- /dev/null
+fn foo(s: &str, a: (i32, i32), s2: &str) {}
+
+fn bar(s: &str, a: (&str,), s2: &str) {}
+
+fn main() {
+ foo("hi", 1, 2, "hi");
+ //~^ ERROR this function takes 3 arguments but 4 arguments were supplied
+ bar("hi", "hi", "hi");
+ //~^ ERROR mismatched types
+}
--- /dev/null
+error[E0061]: this function takes 3 arguments but 4 arguments were supplied
+ --> $DIR/add-tuple-within-arguments.rs:6:5
+ |
+LL | foo("hi", 1, 2, "hi");
+ | ^^^
+ |
+note: function defined here
+ --> $DIR/add-tuple-within-arguments.rs:1:4
+ |
+LL | fn foo(s: &str, a: (i32, i32), s2: &str) {}
+ | ^^^ ------- ------------- --------
+help: wrap these arguments in parentheses to construct a tuple
+ |
+LL | foo("hi", (1, 2), "hi");
+ | + +
+
+error[E0308]: mismatched types
+ --> $DIR/add-tuple-within-arguments.rs:8:15
+ |
+LL | bar("hi", "hi", "hi");
+ | --- ^^^^ expected tuple, found `&str`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected tuple `(&str,)`
+ found reference `&'static str`
+note: function defined here
+ --> $DIR/add-tuple-within-arguments.rs:3:4
+ |
+LL | fn bar(s: &str, a: (&str,), s2: &str) {}
+ | ^^^ ------- ---------- --------
+help: use a trailing comma to create a tuple with one element
+ |
+LL | bar("hi", ("hi",), "hi");
+ | + ++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
|
LL | fn test(t: (i32, i32)) {}
| ^^^^ -------------
-help: use parentheses to construct a tuple
+help: wrap these arguments in parentheses to construct a tuple
|
LL | test((x.qux(), x.qux()));
| + +
--> $DIR/wrong_argument_ice-3.rs:9:16
|
LL | groups.push(new_group, vec![process]);
- | ^^^^ --------- ------------- argument unexpected
+ | ^^^^ --------- ------------- argument of type `Vec<&Process>` unexpected
| |
| expected tuple, found struct `Vec`
|
LL | |
LL | | let b = 1;
LL | | });
- | |_____- argument unexpected
+ | |_____- argument of type `[closure@$DIR/wrong_argument_ice-4.rs:2:13: 5:6]` unexpected
|
note: closure defined here
--> $DIR/wrong_argument_ice-4.rs:2:6
|
LL | pub fn push_back(&mut self, value: T) {
| ^^^^^^^^^
-help: use parentheses to construct a tuple
+help: wrap these arguments in parentheses to construct a tuple
|
LL | self.acc.push_back((self.current_provides, self.current_requires));
| + +
--> $DIR/type-ascription-instead-of-initializer.rs:2:12
|
LL | let x: Vec::with_capacity(10, 20);
- | ^^^^^^^^^^^^^^^^^^ -- argument unexpected
+ | ^^^^^^^^^^^^^^^^^^ -- argument of type `{integer}` unexpected
|
note: associated function defined here
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
--- /dev/null
+fn main() {}
+trait A {
+ fn a(aa: B) -> Result<_, B> {
+ //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+ Ok(())
+ }
+}
+
+enum B {}
--- /dev/null
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/issue-98260.rs:3:27
+ |
+LL | fn a(aa: B) -> Result<_, B> {
+ | -------^----
+ | | |
+ | | not allowed in type signatures
+ | help: replace with the correct return type: `Result<(), B>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
--> $DIR/remove-extra-argument.rs:6:5
|
LL | l(vec![], vec![])
- | ^ ------ argument unexpected
+ | ^ ------ argument of type `Vec<_>` unexpected
|
note: function defined here
--> $DIR/remove-extra-argument.rs:3:4
--> $DIR/struct-enum-wrong-args.rs:6:13
|
LL | let _ = Some(3, 2);
- | ^^^^ - argument unexpected
+ | ^^^^ - argument of type `{integer}` unexpected
|
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
--> $DIR/struct-enum-wrong-args.rs:7:13
|
LL | let _ = Ok(3, 6, 2);
- | ^^ - - argument unexpected
+ | ^^ - - argument of type `{integer}` unexpected
| |
- | argument unexpected
+ | argument of type `{integer}` unexpected
|
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
--> $DIR/struct-enum-wrong-args.rs:10:13
|
LL | let _ = Wrapper(5, 2);
- | ^^^^^^^ - argument unexpected
+ | ^^^^^^^ - argument of type `{integer}` unexpected
|
note: tuple struct defined here
--> $DIR/struct-enum-wrong-args.rs:2:8
--> $DIR/struct-enum-wrong-args.rs:13:13
|
LL | let _ = DoubleWrapper(5, 2, 7);
- | ^^^^^^^^^^^^^ - argument unexpected
+ | ^^^^^^^^^^^^^ - argument of type `{integer}` unexpected
|
note: tuple struct defined here
--> $DIR/struct-enum-wrong-args.rs:3:8
--> $DIR/unop-move-semantics.rs:24:6
|
LL | !*m;
- | ^^ move occurs because `*m` has type `T`, which does not implement the `Copy` trait
+ | -^^
+ | ||
+ | |move occurs because `*m` has type `T`, which does not implement the `Copy` trait
+ | `*m` moved due to usage in operator
+ |
+note: calling this operator moves the left-hand side
+ --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
+ |
+LL | fn not(self) -> Self::Output;
+ | ^^^^
error[E0507]: cannot move out of `*n` which is behind a shared reference
--> $DIR/unop-move-semantics.rs:26:6
|
LL | !*n;
- | ^^ move occurs because `*n` has type `T`, which does not implement the `Copy` trait
+ | -^^
+ | ||
+ | |move occurs because `*n` has type `T`, which does not implement the `Copy` trait
+ | `*n` moved due to usage in operator
error: aborting due to 5 previous errors
fn foo(f: Option<&dyn Foo>) {
if let Some(f) = f {
let _ = f.foo();
- //~^ ERROR cannot move a value of type [u8]: the size of [u8] cannot be statically determined
+ //~^ ERROR cannot move a value of type `[u8]`
}
}
-error[E0161]: cannot move a value of type [u8]: the size of [u8] cannot be statically determined
+error[E0161]: cannot move a value of type `[u8]`
--> $DIR/return-unsized-from-trait-method.rs:9:17
|
LL | let _ = f.foo();
- | ^^^^^^^
+ | ^^^^^^^ the size of `[u8]` cannot be statically determined
error: aborting due to previous error
--> $DIR/unsized-fn-param.rs:11:11
|
LL | foo11("bar", &"baz");
- | ^^^^^ doesn't have a size known at compile-time
+ | ----- ^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `str`
- = note: required for the cast to the object type `dyn AsRef<Path>`
+ = note: required for the cast from `str` to the object type `dyn AsRef<Path>`
help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<Path>`
|
LL | foo11(&"bar", &"baz");
--> $DIR/unsized-fn-param.rs:13:19
|
LL | foo12(&"bar", "baz");
- | ^^^^^ doesn't have a size known at compile-time
+ | ----- ^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `str`
- = note: required for the cast to the object type `dyn AsRef<Path>`
+ = note: required for the cast from `str` to the object type `dyn AsRef<Path>`
help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<Path>`
|
LL | foo12(&"bar", &"baz");
--> $DIR/unsized-fn-param.rs:16:11
|
LL | foo21("bar", &"baz");
- | ^^^^^ doesn't have a size known at compile-time
+ | ----- ^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `str`
- = note: required for the cast to the object type `dyn AsRef<str>`
+ = note: required for the cast from `str` to the object type `dyn AsRef<str>`
help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<str>`
|
LL | foo21(&"bar", &"baz");
--> $DIR/unsized-fn-param.rs:18:19
|
LL | foo22(&"bar", "baz");
- | ^^^^^ doesn't have a size known at compile-time
+ | ----- ^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `str`
- = note: required for the cast to the object type `dyn AsRef<str>`
+ = note: required for the cast from `str` to the object type `dyn AsRef<str>`
help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<str>`
|
LL | foo22(&"bar", &"baz");
fn f10<X: ?Sized>(x1: Box<S<X>>) {
f5(&(32, *x1));
//~^ ERROR the size for values of type
+ //~| ERROR the size for values of type
}
pub fn main() {}
LL + fn f9<X>(x1: Box<S<X>>) {
|
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized3.rs:45:9
+ |
+LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | f5(&(32, *x1));
+ | -- ^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required because it appears within the type `S<X>`
+ --> $DIR/unsized3.rs:28:8
+ |
+LL | struct S<X: ?Sized> {
+ | ^
+ = note: required because it appears within the type `({integer}, S<X>)`
+ = note: tuples must have a statically known size to be initialized
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
+LL + fn f10<X>(x1: Box<S<X>>) {
+ |
+
error[E0277]: the size for values of type `X` cannot be known at compilation time
--> $DIR/unsized3.rs:45:8
|
LL | struct S<X: ?Sized> {
| ^
= note: required because it appears within the type `({integer}, S<X>)`
- = note: tuples must have a statically known size to be initialized
+note: required by a bound in `f5`
+ --> $DIR/unsized3.rs:24:7
+ |
+LL | fn f5<Y>(x: &Y) {}
+ | ^ required by this bound in `f5`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
LL + fn f10<X>(x1: Box<S<X>>) {
|
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | fn f5<Y: ?Sized>(x: &Y) {}
+ | ++++++++
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0277`.
-Subproject commit a5e08c4703f202e30cdaf80ca3e7c00baa59c496
+Subproject commit dbff32b27893b899ae2397f3d56d1be111041d56
rand_core_0_5 = { package = "rand_core", version = "0.5.1", features = ["getrandom", "alloc", "std"] }
serde = { version = "1.0.82", features = ['derive'] }
serde_json = { version = "1.0.31", features = ["raw_value", "unbounded_depth"] }
-smallvec = { version = "1.6.1", features = ['union', 'may_dangle'] }
+smallvec = { version = "1.8.1", features = ['union', 'may_dangle'] }
syn = { version = "1", features = ['fold', 'full', 'extra-traits', 'visit', 'visit-mut'] }
url = { version = "2.0", features = ['serde'] }
[mentions."compiler/rustc_apfloat"]
message = """
-Changes rustc_apfloat. rustc_apfloat is currently in limbo and you almost
+Changes rustc_apfloat. rustc_apfloat is currently in limbo and you almost \
certainly don't want to change it (see #55993).
"""
cc = ["@eddyb"]
message = """
Hey! It looks like you've submitted a new PR for the library teams!
-If this PR contains changes to any `rust-lang/rust` public library APIs then
-please comment with `@rustbot label +T-libs-api -T-libs` to tag it
-appropriately. If this PR contains changes to any unstable APIs please edit
-the PR description to add a link to the relevant [API Change
-Proposal](https://std-dev-guide.rust-lang.org/feature-lifecycle/api-change-proposals.html)
-or [create one](https://github.com/rust-lang/libs-team/issues/new?assignees=&labels=api-change-proposal%2C+T-libs-api&template=api-change-proposal.md&title=%28My+API+Change+Proposal%29)
-if you haven't already. If you're unsure where your change falls no worries,
-just leave it as is and the reviewer will take a look and make a decision to
+If this PR contains changes to any `rust-lang/rust` public library APIs then \
+please comment with `@rustbot label +T-libs-api -T-libs` to tag it \
+appropriately. If this PR contains changes to any unstable APIs please edit \
+the PR description to add a link to the relevant [API Change \
+Proposal](https://std-dev-guide.rust-lang.org/feature-lifecycle/api-change-proposals.html) \
+or [create one](https://github.com/rust-lang/libs-team/issues/new?assignees=&labels=api-change-proposal%2C+T-libs-api&template=api-change-proposal.md&title=%28My+API+Change+Proposal%29) \
+if you haven't already. If you're unsure where your change falls no worries, \
+just leave it as is and the reviewer will take a look and make a decision to \
forward on if necessary.
Examples of `T-libs-api` changes:
* Stabilizing library features
-* Introducing insta-stable changes such as new implementations of existing
+* Introducing insta-stable changes such as new implementations of existing \
stable traits on existing stable types
-* Introducing new or changing existing unstable library APIs (excluding
+* Introducing new or changing existing unstable library APIs (excluding \
permanently unstable features / features without a tracking issue)
* Changing public documentation in ways that create new stability guarantees
* Changing observable runtime behavior of library APIs
[mentions."src/rustdoc-json-types"]
message = """
-rustdoc-json-types is a **public** (although nightly-only) API.
-If possible, consider changing `src/librustdoc/json/conversions.rs`;
+rustdoc-json-types is a **public** (although nightly-only) API. \
+If possible, consider changing `src/librustdoc/json/conversions.rs`; \
otherwise, make sure you bump the `FORMAT_VERSION` constant.
"""
cc = [