Auto merge of #88329 - LeSeulArtichaut:rollup-blg8hc0, r=LeSeulArtichaut
Rollup of 16 pull requests Successful merges: - #87944 (add Cell::as_array_of_cells, similar to Cell::as_slice_of_cells) - #88156 (Adjust / fix documentation of `Arc::make_mut`) - #88157 (bootstrap.py: recognize riscv64 when auto-detect) - #88196 (Refactor `named_asm_labels` to a HIR lint) - #88218 (Remove `Session.trait_methods_not_found`) - #88223 (Remove the `TryV2` alias) - #88226 (Fix typo “a Rc” → “an Rc” (and a few more)) - #88267 (2229: Update signature for truncate function) - #88273 (Fix references to `ControlFlow` in docs) - #88277 (Update books) - #88291 (Add SAFETY comments to core::slice::sort::partition_in_blocks) - #88293 (Fix grammar in alloc test) - #88298 (Errorkind reorder) - #88299 (Stabilise BufWriter::into_parts) - #88314 (Add type of a let tait test) - #88325 (Add mutable-noalias to the release notes for 1.54) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7b0e554ee2
45 changed files with 686 additions and 323 deletions
|
@ -175,6 +175,7 @@ Compiler
|
|||
- [Improved debugger output for enums on Windows MSVC platforms.][85292]
|
||||
- [Added tier 3\* support for `bpfel-unknown-none`
|
||||
and `bpfeb-unknown-none`.][79608]
|
||||
- [`-Zmutable-noalias=yes`][82834] is enabled by default when using LLVM 12 or above.
|
||||
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
@ -244,6 +245,7 @@ Compatibility Notes
|
|||
[83366]: https://github.com/rust-lang/rust/pull/83366
|
||||
[83278]: https://github.com/rust-lang/rust/pull/83278
|
||||
[85292]: https://github.com/rust-lang/rust/pull/85292
|
||||
[82834]: https://github.com/rust-lang/rust/pull/82834
|
||||
[cargo/9520]: https://github.com/rust-lang/cargo/pull/9520
|
||||
[cargo/9499]: https://github.com/rust-lang/cargo/pull/9499
|
||||
[cargo/9488]: https://github.com/rust-lang/cargo/pull/9488
|
||||
|
|
|
@ -2028,6 +2028,7 @@ pub enum InlineAsmOperand {
|
|||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct InlineAsm {
|
||||
pub template: Vec<InlineAsmTemplatePiece>,
|
||||
pub template_strs: Box<[(Symbol, Option<Symbol>, Span)]>,
|
||||
pub operands: Vec<(InlineAsmOperand, Span)>,
|
||||
pub clobber_abi: Option<(Symbol, Span)>,
|
||||
pub options: InlineAsmOptions,
|
||||
|
|
|
@ -19,20 +19,20 @@ use crate::token;
|
|||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum AssocCtxt {
|
||||
Trait,
|
||||
Impl,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum FnCtxt {
|
||||
Free,
|
||||
Foreign,
|
||||
Assoc(AssocCtxt),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum FnKind<'a> {
|
||||
/// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
|
||||
Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, Option<&'a Block>),
|
||||
|
|
|
@ -392,8 +392,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
let operands = self.arena.alloc_from_iter(operands);
|
||||
let template = self.arena.alloc_from_iter(asm.template.iter().cloned());
|
||||
let template_strs = self.arena.alloc_from_iter(asm.template_strs.iter().cloned());
|
||||
let line_spans = self.arena.alloc_slice(&asm.line_spans[..]);
|
||||
let hir_asm = hir::InlineAsm { template, operands, options: asm.options, line_spans };
|
||||
let hir_asm =
|
||||
hir::InlineAsm { template, template_strs, operands, options: asm.options, line_spans };
|
||||
self.arena.alloc(hir_asm)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
|
|||
use rustc_expand::base::{self, *};
|
||||
use rustc_parse::parser::Parser;
|
||||
use rustc_parse_format as parse;
|
||||
use rustc_session::lint::{self, BuiltinLintDiagnostics};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::{InnerSpan, MultiSpan, Span};
|
||||
use rustc_span::{InnerSpan, Span};
|
||||
use rustc_target::asm::InlineAsmArch;
|
||||
use smallvec::smallvec;
|
||||
|
||||
|
@ -484,11 +484,7 @@ fn parse_reg<'a>(
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
fn expand_preparsed_asm(
|
||||
ecx: &mut ExtCtxt<'_>,
|
||||
args: AsmArgs,
|
||||
is_local_asm: bool,
|
||||
) -> Option<ast::InlineAsm> {
|
||||
fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::InlineAsm> {
|
||||
let mut template = vec![];
|
||||
// Register operands are implicitly used since they are not allowed to be
|
||||
// referenced in the template string.
|
||||
|
@ -501,6 +497,8 @@ fn expand_preparsed_asm(
|
|||
let mut line_spans = Vec::with_capacity(args.templates.len());
|
||||
let mut curarg = 0;
|
||||
|
||||
let mut template_strs = Vec::with_capacity(args.templates.len());
|
||||
|
||||
for template_expr in args.templates.into_iter() {
|
||||
if !template.is_empty() {
|
||||
template.push(ast::InlineAsmTemplatePiece::String("\n".to_string()));
|
||||
|
@ -524,8 +522,13 @@ fn expand_preparsed_asm(
|
|||
ast::StrStyle::Raw(raw) => Some(raw as usize),
|
||||
};
|
||||
|
||||
let template_str = &template_str.as_str();
|
||||
let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok();
|
||||
template_strs.push((
|
||||
template_str,
|
||||
template_snippet.as_ref().map(|s| Symbol::intern(s)),
|
||||
template_sp,
|
||||
));
|
||||
let template_str = &template_str.as_str();
|
||||
|
||||
if let Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) = ecx.sess.asm_arch {
|
||||
let find_span = |needle: &str| -> Span {
|
||||
|
@ -560,72 +563,6 @@ fn expand_preparsed_asm(
|
|||
}
|
||||
}
|
||||
|
||||
// Lint against the use of named labels in inline `asm!` but not `global_asm!`
|
||||
if is_local_asm {
|
||||
let find_label_span = |needle: &str| -> Option<Span> {
|
||||
if let Some(snippet) = &template_snippet {
|
||||
if let Some(pos) = snippet.find(needle) {
|
||||
let end = pos
|
||||
+ &snippet[pos..]
|
||||
.find(|c| c == ':')
|
||||
.unwrap_or(snippet[pos..].len() - 1);
|
||||
let inner = InnerSpan::new(pos, end);
|
||||
return Some(template_sp.from_inner(inner));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
};
|
||||
|
||||
let mut found_labels = Vec::new();
|
||||
|
||||
// A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always
|
||||
let statements = template_str.split(|c| matches!(c, '\n' | ';'));
|
||||
for statement in statements {
|
||||
// If there's a comment, trim it from the statement
|
||||
let statement = statement.find("//").map_or(statement, |idx| &statement[..idx]);
|
||||
let mut start_idx = 0;
|
||||
for (idx, _) in statement.match_indices(':') {
|
||||
let possible_label = statement[start_idx..idx].trim();
|
||||
let mut chars = possible_label.chars();
|
||||
if let Some(c) = chars.next() {
|
||||
// A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
|
||||
if (c.is_alphabetic() || matches!(c, '.' | '_'))
|
||||
&& chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
|
||||
{
|
||||
found_labels.push(possible_label);
|
||||
} else {
|
||||
// If we encounter a non-label, there cannot be any further labels, so stop checking
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Empty string means a leading ':' in this section, which is not a label
|
||||
break;
|
||||
}
|
||||
|
||||
start_idx = idx + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if found_labels.len() > 0 {
|
||||
let spans =
|
||||
found_labels.into_iter().filter_map(find_label_span).collect::<Vec<Span>>();
|
||||
// If there were labels but we couldn't find a span, combine the warnings and use the template span
|
||||
let target_spans: MultiSpan =
|
||||
if spans.len() > 0 { spans.into() } else { template_sp.into() };
|
||||
ecx.parse_sess().buffer_lint_with_diagnostic(
|
||||
lint::builtin::NAMED_ASM_LABELS,
|
||||
target_spans,
|
||||
ecx.current_expansion.lint_node_id,
|
||||
"avoid using named labels in inline assembly",
|
||||
BuiltinLintDiagnostics::NamedAsmLabel(
|
||||
"only local labels of the form `<number>:` should be used in inline asm"
|
||||
.to_string(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't treat raw asm as a format string.
|
||||
if args.options.contains(ast::InlineAsmOptions::RAW) {
|
||||
template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string()));
|
||||
|
@ -819,6 +756,7 @@ fn expand_preparsed_asm(
|
|||
|
||||
Some(ast::InlineAsm {
|
||||
template,
|
||||
template_strs: template_strs.into_boxed_slice(),
|
||||
operands: args.operands,
|
||||
clobber_abi: args.clobber_abi,
|
||||
options: args.options,
|
||||
|
@ -833,7 +771,7 @@ pub fn expand_asm<'cx>(
|
|||
) -> Box<dyn base::MacResult + 'cx> {
|
||||
match parse_args(ecx, sp, tts, false) {
|
||||
Ok(args) => {
|
||||
let expr = if let Some(inline_asm) = expand_preparsed_asm(ecx, args, true) {
|
||||
let expr = if let Some(inline_asm) = expand_preparsed_asm(ecx, args) {
|
||||
P(ast::Expr {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::ExprKind::InlineAsm(P(inline_asm)),
|
||||
|
@ -860,7 +798,7 @@ pub fn expand_global_asm<'cx>(
|
|||
) -> Box<dyn base::MacResult + 'cx> {
|
||||
match parse_args(ecx, sp, tts, true) {
|
||||
Ok(args) => {
|
||||
if let Some(inline_asm) = expand_preparsed_asm(ecx, args, false) {
|
||||
if let Some(inline_asm) = expand_preparsed_asm(ecx, args) {
|
||||
MacEager::items(smallvec![P(ast::Item {
|
||||
ident: Ident::invalid(),
|
||||
attrs: Vec::new(),
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
This crate provides the _owning reference_ types `OwningRef` and `OwningRefMut`
|
||||
that enables it to bundle a reference together with the owner of the data it points to.
|
||||
This allows moving and dropping of a `OwningRef` without needing to recreate the reference.
|
||||
This allows moving and dropping of an `OwningRef` without needing to recreate the reference.
|
||||
|
||||
This can sometimes be useful because Rust borrowing rules normally prevent
|
||||
moving a type that has been moved from. For example, this kind of code gets rejected:
|
||||
|
@ -1146,7 +1146,7 @@ pub type VecRef<T, U = T> = OwningRef<Vec<T>, U>;
|
|||
/// Typedef of an owning reference that uses a `String` as the owner.
|
||||
pub type StringRef = OwningRef<String, str>;
|
||||
|
||||
/// Typedef of an owning reference that uses a `Rc` as the owner.
|
||||
/// Typedef of an owning reference that uses an `Rc` as the owner.
|
||||
pub type RcRef<T, U = T> = OwningRef<Rc<T>, U>;
|
||||
/// Typedef of an owning reference that uses an `Arc` as the owner.
|
||||
pub type ArcRef<T, U = T> = OwningRef<Arc<T>, U>;
|
||||
|
@ -1157,9 +1157,9 @@ pub type RefRef<'a, T, U = T> = OwningRef<Ref<'a, T>, U>;
|
|||
pub type RefMutRef<'a, T, U = T> = OwningRef<RefMut<'a, T>, U>;
|
||||
/// Typedef of an owning reference that uses a `MutexGuard` as the owner.
|
||||
pub type MutexGuardRef<'a, T, U = T> = OwningRef<MutexGuard<'a, T>, U>;
|
||||
/// Typedef of an owning reference that uses a `RwLockReadGuard` as the owner.
|
||||
/// Typedef of an owning reference that uses an `RwLockReadGuard` as the owner.
|
||||
pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef<RwLockReadGuard<'a, T>, U>;
|
||||
/// Typedef of an owning reference that uses a `RwLockWriteGuard` as the owner.
|
||||
/// Typedef of an owning reference that uses an `RwLockWriteGuard` as the owner.
|
||||
pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
|
||||
|
||||
/// Typedef of a mutable owning reference that uses a `Box` as the owner.
|
||||
|
@ -1173,7 +1173,7 @@ pub type StringRefMut = OwningRefMut<String, str>;
|
|||
pub type RefMutRefMut<'a, T, U = T> = OwningRefMut<RefMut<'a, T>, U>;
|
||||
/// Typedef of a mutable owning reference that uses a `MutexGuard` as the owner.
|
||||
pub type MutexGuardRefMut<'a, T, U = T> = OwningRefMut<MutexGuard<'a, T>, U>;
|
||||
/// Typedef of a mutable owning reference that uses a `RwLockWriteGuard` as the owner.
|
||||
/// Typedef of a mutable owning reference that uses an `RwLockWriteGuard` as the owner.
|
||||
pub type RwLockWriteGuardRefMut<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
|
||||
|
||||
unsafe impl<'a, T: 'a> IntoErased<'a> for Box<T> {
|
||||
|
|
|
@ -2386,6 +2386,7 @@ impl<'hir> InlineAsmOperand<'hir> {
|
|||
#[derive(Debug, HashStable_Generic)]
|
||||
pub struct InlineAsm<'hir> {
|
||||
pub template: &'hir [InlineAsmTemplatePiece],
|
||||
pub template_strs: &'hir [(Symbol, Option<Symbol>, Span)],
|
||||
pub operands: &'hir [(InlineAsmOperand<'hir>, Span)],
|
||||
pub options: InlineAsmOptions,
|
||||
pub line_spans: &'hir [Span],
|
||||
|
|
|
@ -104,11 +104,5 @@ pub fn report_object_safety_error(
|
|||
to be resolvable dynamically; for more information visit \
|
||||
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
|
||||
);
|
||||
|
||||
if tcx.sess.trait_methods_not_found.borrow().iter().any(|full_span| full_span.contains(span)) {
|
||||
// Avoid emitting error caused by non-existing method (#58734)
|
||||
err.cancel();
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
|
|
|
@ -45,11 +45,11 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
|
|||
use rustc_middle::ty::subst::{GenericArgKind, Subst};
|
||||
use rustc_middle::ty::Instance;
|
||||
use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt};
|
||||
use rustc_session::lint::FutureIncompatibilityReason;
|
||||
use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{BytePos, Span};
|
||||
use rustc_span::{BytePos, InnerSpan, MultiSpan, Span};
|
||||
use rustc_target::abi::{LayoutOf, VariantIdx};
|
||||
use rustc_trait_selection::traits::misc::can_type_implement_copy;
|
||||
|
||||
|
@ -3140,3 +3140,123 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `named_asm_labels` lint detects the use of named labels in the
|
||||
/// inline `asm!` macro.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![feature(asm)]
|
||||
/// fn main() {
|
||||
/// unsafe {
|
||||
/// asm!("foo: bar");
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// LLVM is allowed to duplicate inline assembly blocks for any
|
||||
/// reason, for example when it is in a function that gets inlined. Because
|
||||
/// of this, GNU assembler [local labels] *must* be used instead of labels
|
||||
/// with a name. Using named labels might cause assembler or linker errors.
|
||||
///
|
||||
/// See the [unstable book] for more details.
|
||||
///
|
||||
/// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels
|
||||
/// [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels
|
||||
pub NAMED_ASM_LABELS,
|
||||
Deny,
|
||||
"named labels in inline assembly",
|
||||
}
|
||||
|
||||
declare_lint_pass!(NamedAsmLabels => [NAMED_ASM_LABELS]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
|
||||
if let hir::Expr {
|
||||
kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, .. }),
|
||||
..
|
||||
} = expr
|
||||
{
|
||||
for (template_sym, template_snippet, template_span) in template_strs.iter() {
|
||||
let template_str = &template_sym.as_str();
|
||||
let find_label_span = |needle: &str| -> Option<Span> {
|
||||
if let Some(template_snippet) = template_snippet {
|
||||
let snippet = template_snippet.as_str();
|
||||
if let Some(pos) = snippet.find(needle) {
|
||||
let end = pos
|
||||
+ &snippet[pos..]
|
||||
.find(|c| c == ':')
|
||||
.unwrap_or(snippet[pos..].len() - 1);
|
||||
let inner = InnerSpan::new(pos, end);
|
||||
return Some(template_span.from_inner(inner));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
};
|
||||
|
||||
let mut found_labels = Vec::new();
|
||||
|
||||
// A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always
|
||||
let statements = template_str.split(|c| matches!(c, '\n' | ';'));
|
||||
for statement in statements {
|
||||
// If there's a comment, trim it from the statement
|
||||
let statement = statement.find("//").map_or(statement, |idx| &statement[..idx]);
|
||||
let mut start_idx = 0;
|
||||
for (idx, _) in statement.match_indices(':') {
|
||||
let possible_label = statement[start_idx..idx].trim();
|
||||
let mut chars = possible_label.chars();
|
||||
if let Some(c) = chars.next() {
|
||||
// A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
|
||||
if (c.is_alphabetic() || matches!(c, '.' | '_'))
|
||||
&& chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
|
||||
{
|
||||
found_labels.push(possible_label);
|
||||
} else {
|
||||
// If we encounter a non-label, there cannot be any further labels, so stop checking
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Empty string means a leading ':' in this section, which is not a label
|
||||
break;
|
||||
}
|
||||
|
||||
start_idx = idx + 1;
|
||||
}
|
||||
}
|
||||
|
||||
debug!("NamedAsmLabels::check_expr(): found_labels: {:#?}", &found_labels);
|
||||
|
||||
if found_labels.len() > 0 {
|
||||
let spans = found_labels
|
||||
.into_iter()
|
||||
.filter_map(|label| find_label_span(label))
|
||||
.collect::<Vec<Span>>();
|
||||
// If there were labels but we couldn't find a span, combine the warnings and use the template span
|
||||
let target_spans: MultiSpan =
|
||||
if spans.len() > 0 { spans.into() } else { (*template_span).into() };
|
||||
|
||||
cx.lookup_with_diagnostics(
|
||||
NAMED_ASM_LABELS,
|
||||
Some(target_spans),
|
||||
|diag| {
|
||||
let mut err =
|
||||
diag.build("avoid using named labels in inline assembly");
|
||||
err.emit();
|
||||
},
|
||||
BuiltinLintDiagnostics::NamedAsmLabel(
|
||||
"only local labels of the form `<number>:` should be used in inline asm"
|
||||
.to_string(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,6 +168,7 @@ macro_rules! late_lint_passes {
|
|||
NonPanicFmt: NonPanicFmt,
|
||||
NoopMethodCall: NoopMethodCall,
|
||||
InvalidAtomicOrdering: InvalidAtomicOrdering,
|
||||
NamedAsmLabels: NamedAsmLabels,
|
||||
]
|
||||
);
|
||||
};
|
||||
|
|
|
@ -2468,38 +2468,6 @@ declare_lint! {
|
|||
"incorrect use of inline assembly",
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `named_asm_labels` lint detects the use of named labels in the
|
||||
/// inline `asm!` macro.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// fn main() {
|
||||
/// unsafe {
|
||||
/// asm!("foo: bar");
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// LLVM is allowed to duplicate inline assembly blocks for any
|
||||
/// reason, for example when it is in a function that gets inlined. Because
|
||||
/// of this, GNU assembler [local labels] *must* be used instead of labels
|
||||
/// with a name. Using named labels might cause assembler or linker errors.
|
||||
///
|
||||
/// See the [unstable book] for more details.
|
||||
///
|
||||
/// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels
|
||||
/// [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels
|
||||
pub NAMED_ASM_LABELS,
|
||||
Deny,
|
||||
"named labels in inline assembly",
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `unsafe_op_in_unsafe_fn` lint detects unsafe operations in unsafe
|
||||
/// functions without an explicit unsafe block.
|
||||
|
@ -3020,7 +2988,6 @@ declare_lint_pass! {
|
|||
INLINE_NO_SANITIZE,
|
||||
BAD_ASM_STYLE,
|
||||
ASM_SUB_REGISTER,
|
||||
NAMED_ASM_LABELS,
|
||||
UNSAFE_OP_IN_UNSAFE_FN,
|
||||
INCOMPLETE_INCLUDE,
|
||||
CENUM_IMPL_DROP_CAST,
|
||||
|
|
|
@ -189,9 +189,6 @@ pub struct Session {
|
|||
/// Cap lint level specified by a driver specifically.
|
||||
pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
|
||||
|
||||
/// `Span`s of trait methods that weren't found to avoid emitting object safety errors
|
||||
pub trait_methods_not_found: Lock<FxHashSet<Span>>,
|
||||
|
||||
/// Mapping from ident span to path span for paths that don't exist as written, but that
|
||||
/// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
|
||||
pub confused_type_with_std_module: Lock<FxHashMap<Span, Span>>,
|
||||
|
@ -1326,7 +1323,6 @@ pub fn build_session(
|
|||
print_fuel,
|
||||
jobserver: jobserver::client(),
|
||||
driver_lint_caps,
|
||||
trait_methods_not_found: Lock::new(Default::default()),
|
||||
confused_type_with_std_module: Lock::new(Default::default()),
|
||||
ctfe_backtrace,
|
||||
miri_unleashed_features: Lock::new(Default::default()),
|
||||
|
|
|
@ -858,13 +858,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
path.segments,
|
||||
);
|
||||
}
|
||||
QPath::TypeRelative(ref qself, ref segment) => (self.to_ty(qself), qself, segment),
|
||||
QPath::TypeRelative(ref qself, ref segment) => {
|
||||
// Don't use `self.to_ty`, since this will register a WF obligation.
|
||||
// If we're trying to call a non-existent method on a trait
|
||||
// (e.g. `MyTrait::missing_method`), then resolution will
|
||||
// give us a `QPath::TypeRelative` with a trait object as
|
||||
// `qself`. In that case, we want to avoid registering a WF obligation
|
||||
// for `dyn MyTrait`, since we don't actually need the trait
|
||||
// to be object-safe.
|
||||
// We manually call `register_wf_obligation` in the success path
|
||||
// below.
|
||||
(<dyn AstConv<'_>>::ast_ty_to_ty(self, qself), qself, segment)
|
||||
}
|
||||
QPath::LangItem(..) => {
|
||||
bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
|
||||
}
|
||||
};
|
||||
if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
|
||||
{
|
||||
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
|
||||
// Return directly on cache hit. This is useful to avoid doubly reporting
|
||||
// errors with default match binding modes. See #44614.
|
||||
let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
|
||||
|
@ -878,6 +890,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
|
||||
_ => Err(ErrorReported),
|
||||
};
|
||||
|
||||
// If we have a path like `MyTrait::missing_method`, then don't register
|
||||
// a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
|
||||
// register a WF obligation so that we can detect any additional
|
||||
// errors in the self type.
|
||||
if !(matches!(error, method::MethodError::NoMatch(_)) && ty.is_trait()) {
|
||||
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
|
||||
}
|
||||
if item_name.name != kw::Empty {
|
||||
if let Some(mut e) = self.report_method_error(
|
||||
span,
|
||||
|
@ -895,6 +915,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
if result.is_ok() {
|
||||
self.maybe_lint_bare_trait(qpath, hir_id);
|
||||
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
|
||||
}
|
||||
|
||||
// Write back the new resolution.
|
||||
|
|
|
@ -70,15 +70,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
pub fn report_method_error(
|
||||
&self,
|
||||
span: Span,
|
||||
mut span: Span,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
item_name: Ident,
|
||||
source: SelfSource<'tcx>,
|
||||
error: MethodError<'tcx>,
|
||||
args: Option<&'tcx [hir::Expr<'tcx>]>,
|
||||
) -> Option<DiagnosticBuilder<'_>> {
|
||||
let orig_span = span;
|
||||
let mut span = span;
|
||||
// Avoid suggestions when we don't know what's going on.
|
||||
if rcvr_ty.references_error() {
|
||||
return None;
|
||||
|
@ -545,7 +543,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
|
||||
}
|
||||
self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
|
||||
};
|
||||
|
||||
// If the method name is the name of a field with a function or closure type,
|
||||
|
|
|
@ -489,7 +489,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mut root_var_min_capture_list =
|
||||
typeck_results.closure_min_captures.remove(&closure_def_id).unwrap_or_default();
|
||||
|
||||
for (place, capture_info) in capture_information.into_iter() {
|
||||
for (mut place, capture_info) in capture_information.into_iter() {
|
||||
let var_hir_id = match place.base {
|
||||
PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
|
||||
base => bug!("Expected upvar, found={:?}", base),
|
||||
|
@ -530,14 +530,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Truncate the descendant (already in min_captures) to be same as the ancestor to handle any
|
||||
// possible change in capture mode.
|
||||
let (_, descendant_capture_kind) = truncate_place_to_len(
|
||||
possible_descendant.place,
|
||||
possible_descendant.info.capture_kind,
|
||||
truncate_place_to_len_and_update_capture_kind(
|
||||
&mut possible_descendant.place,
|
||||
&mut possible_descendant.info.capture_kind,
|
||||
place.projections.len(),
|
||||
);
|
||||
|
||||
possible_descendant.info.capture_kind = descendant_capture_kind;
|
||||
|
||||
updated_capture_info =
|
||||
determine_capture_info(updated_capture_info, possible_descendant.info);
|
||||
|
||||
|
@ -561,14 +559,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Truncate the descendant (current place) to be same as the ancestor to handle any
|
||||
// possible change in capture mode.
|
||||
let (_, descendant_capture_kind) = truncate_place_to_len(
|
||||
place.clone(),
|
||||
updated_capture_info.capture_kind,
|
||||
truncate_place_to_len_and_update_capture_kind(
|
||||
&mut place,
|
||||
&mut updated_capture_info.capture_kind,
|
||||
possible_ancestor.place.projections.len(),
|
||||
);
|
||||
|
||||
updated_capture_info.capture_kind = descendant_capture_kind;
|
||||
|
||||
possible_ancestor.info = determine_capture_info(
|
||||
possible_ancestor.info,
|
||||
updated_capture_info,
|
||||
|
@ -1476,7 +1472,7 @@ fn restrict_repr_packed_field_ref_capture<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
place: &Place<'tcx>,
|
||||
curr_borrow_kind: ty::UpvarCapture<'tcx>,
|
||||
mut curr_borrow_kind: ty::UpvarCapture<'tcx>,
|
||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
||||
let pos = place.projections.iter().enumerate().position(|(i, p)| {
|
||||
let ty = place.ty_before_projection(i);
|
||||
|
@ -1508,13 +1504,13 @@ fn restrict_repr_packed_field_ref_capture<'tcx>(
|
|||
}
|
||||
});
|
||||
|
||||
let place = place.clone();
|
||||
let mut place = place.clone();
|
||||
|
||||
if let Some(pos) = pos {
|
||||
truncate_place_to_len(place, curr_borrow_kind, pos)
|
||||
} else {
|
||||
(place, curr_borrow_kind)
|
||||
truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_borrow_kind, pos);
|
||||
}
|
||||
|
||||
(place, curr_borrow_kind)
|
||||
}
|
||||
|
||||
/// Returns a Ty that applies the specified capture kind on the provided capture Ty
|
||||
|
@ -1841,31 +1837,28 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
|
|||
/// them completely.
|
||||
/// - No projections are applied on top of Union ADTs, since these require unsafe blocks.
|
||||
fn restrict_precision_for_unsafe(
|
||||
place: Place<'tcx>,
|
||||
curr_mode: ty::UpvarCapture<'tcx>,
|
||||
mut place: Place<'tcx>,
|
||||
mut curr_mode: ty::UpvarCapture<'tcx>,
|
||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
||||
if place.projections.is_empty() {
|
||||
// Nothing to do here
|
||||
return (place, curr_mode);
|
||||
}
|
||||
|
||||
if place.base_ty.is_unsafe_ptr() {
|
||||
return truncate_place_to_len(place, curr_mode, 0);
|
||||
truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, 0);
|
||||
}
|
||||
|
||||
if place.base_ty.is_union() {
|
||||
return truncate_place_to_len(place, curr_mode, 0);
|
||||
truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, 0);
|
||||
}
|
||||
|
||||
for (i, proj) in place.projections.iter().enumerate() {
|
||||
if proj.ty.is_unsafe_ptr() {
|
||||
// Don't apply any projections on top of an unsafe ptr.
|
||||
return truncate_place_to_len(place, curr_mode, i + 1);
|
||||
truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if proj.ty.is_union() {
|
||||
// Don't capture preicse fields of a union.
|
||||
return truncate_place_to_len(place, curr_mode, i + 1);
|
||||
truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1880,7 +1873,7 @@ fn restrict_capture_precision<'tcx>(
|
|||
place: Place<'tcx>,
|
||||
curr_mode: ty::UpvarCapture<'tcx>,
|
||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
||||
let (place, curr_mode) = restrict_precision_for_unsafe(place, curr_mode);
|
||||
let (mut place, mut curr_mode) = restrict_precision_for_unsafe(place, curr_mode);
|
||||
|
||||
if place.projections.is_empty() {
|
||||
// Nothing to do here
|
||||
|
@ -1891,7 +1884,8 @@ fn restrict_capture_precision<'tcx>(
|
|||
match proj.kind {
|
||||
ProjectionKind::Index => {
|
||||
// Arrays are completely captured, so we drop Index projections
|
||||
return truncate_place_to_len(place, curr_mode, i);
|
||||
truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i);
|
||||
return (place, curr_mode);
|
||||
}
|
||||
ProjectionKind::Deref => {}
|
||||
ProjectionKind::Field(..) => {} // ignore
|
||||
|
@ -1906,8 +1900,8 @@ fn restrict_capture_precision<'tcx>(
|
|||
/// (or if closure attempts to move data that it doesn’t own).
|
||||
/// Note: When taking ownership, only capture data found on the stack.
|
||||
fn adjust_for_move_closure<'tcx>(
|
||||
place: Place<'tcx>,
|
||||
kind: ty::UpvarCapture<'tcx>,
|
||||
mut place: Place<'tcx>,
|
||||
mut kind: ty::UpvarCapture<'tcx>,
|
||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
||||
let contains_deref_of_ref = place.deref_tys().any(|ty| ty.is_ref());
|
||||
let first_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
|
||||
|
@ -1917,54 +1911,40 @@ fn adjust_for_move_closure<'tcx>(
|
|||
|
||||
// If there's any Deref and the data needs to be moved into the closure body,
|
||||
// or it's a Deref of a Box, truncate the path to the first deref
|
||||
_ if first_deref.is_some() => {
|
||||
let place = match first_deref {
|
||||
Some(idx) => {
|
||||
let (place, _) = truncate_place_to_len(place, kind, idx);
|
||||
place
|
||||
_ => {
|
||||
if let Some(idx) = first_deref {
|
||||
truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx);
|
||||
}
|
||||
None => place,
|
||||
};
|
||||
|
||||
// AMAN: I think we don't need the span inside the ByValue anymore
|
||||
// we have more detailed span in CaptureInfo
|
||||
(place, ty::UpvarCapture::ByValue(None))
|
||||
}
|
||||
|
||||
_ => (place, ty::UpvarCapture::ByValue(None)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adjust closure capture just that if taking ownership of data, only move data
|
||||
/// from enclosing stack frame.
|
||||
fn adjust_for_non_move_closure<'tcx>(
|
||||
place: Place<'tcx>,
|
||||
mut place: Place<'tcx>,
|
||||
mut kind: ty::UpvarCapture<'tcx>,
|
||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
||||
let contains_deref =
|
||||
place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
|
||||
|
||||
match kind {
|
||||
ty::UpvarCapture::ByValue(..) if contains_deref.is_some() => {
|
||||
let place = match contains_deref {
|
||||
Some(idx) => {
|
||||
let (place, new_kind) = truncate_place_to_len(place, kind, idx);
|
||||
|
||||
kind = new_kind;
|
||||
place
|
||||
ty::UpvarCapture::ByValue(..) => {
|
||||
if let Some(idx) = contains_deref {
|
||||
truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx);
|
||||
}
|
||||
}
|
||||
|
||||
ty::UpvarCapture::ByRef(..) => {}
|
||||
}
|
||||
// Because of the if guard on the match on `kind`, we should never get here.
|
||||
None => unreachable!(),
|
||||
};
|
||||
|
||||
(place, kind)
|
||||
}
|
||||
|
||||
ty::UpvarCapture::ByValue(..) => (place, kind),
|
||||
ty::UpvarCapture::ByRef(..) => (place, kind),
|
||||
}
|
||||
}
|
||||
|
||||
fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String {
|
||||
let variable_name = match place.base {
|
||||
PlaceBase::Upvar(upvar_id) => var_name(tcx, upvar_id.var_path.hir_id).to_string(),
|
||||
|
@ -2157,15 +2137,13 @@ fn determine_capture_info(
|
|||
///
|
||||
/// Note: Capture kind changes from `MutBorrow` to `UniqueImmBorrow` if the truncated part of the `place`
|
||||
/// contained `Deref` of `&mut`.
|
||||
fn truncate_place_to_len(
|
||||
mut place: Place<'tcx>,
|
||||
curr_mode: ty::UpvarCapture<'tcx>,
|
||||
fn truncate_place_to_len_and_update_capture_kind(
|
||||
place: &mut Place<'tcx>,
|
||||
curr_mode: &mut ty::UpvarCapture<'tcx>,
|
||||
len: usize,
|
||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
||||
) {
|
||||
let is_mut_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Mut));
|
||||
|
||||
let mut capture_kind = curr_mode;
|
||||
|
||||
// If the truncated part of the place contains `Deref` of a `&mut` then convert MutBorrow ->
|
||||
// UniqueImmBorrow
|
||||
// Note that if the place contained Deref of a raw pointer it would've not been MutBorrow, so
|
||||
|
@ -2176,7 +2154,7 @@ fn truncate_place_to_len(
|
|||
if place.projections[i].kind == ProjectionKind::Deref
|
||||
&& is_mut_ref(place.ty_before_projection(i))
|
||||
{
|
||||
capture_kind = ty::UpvarCapture::ByRef(ty::UpvarBorrow {
|
||||
*curr_mode = ty::UpvarCapture::ByRef(ty::UpvarBorrow {
|
||||
kind: ty::BorrowKind::UniqueImmBorrow,
|
||||
region,
|
||||
});
|
||||
|
@ -2190,8 +2168,6 @@ fn truncate_place_to_len(
|
|||
}
|
||||
|
||||
place.projections.truncate(len);
|
||||
|
||||
(place, capture_kind)
|
||||
}
|
||||
|
||||
/// Determines the Ancestry relationship of Place A relative to Place B
|
||||
|
@ -2256,8 +2232,8 @@ fn determine_place_ancestry_relation(
|
|||
/// }
|
||||
/// ```
|
||||
fn truncate_capture_for_optimization<'tcx>(
|
||||
place: Place<'tcx>,
|
||||
curr_mode: ty::UpvarCapture<'tcx>,
|
||||
mut place: Place<'tcx>,
|
||||
mut curr_mode: ty::UpvarCapture<'tcx>,
|
||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
||||
let is_shared_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not));
|
||||
|
||||
|
@ -2269,10 +2245,12 @@ fn truncate_capture_for_optimization<'tcx>(
|
|||
match idx {
|
||||
// If that pointer is a shared reference, then we don't need those fields.
|
||||
Some(idx) if is_shared_ref(place.ty_before_projection(idx)) => {
|
||||
truncate_place_to_len(place, curr_mode, idx + 1)
|
||||
truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, idx + 1)
|
||||
}
|
||||
None | Some(_) => (place, curr_mode),
|
||||
None | Some(_) => {}
|
||||
}
|
||||
|
||||
(place, curr_mode)
|
||||
}
|
||||
|
||||
/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
|
||||
|
|
|
@ -1011,7 +1011,7 @@ impl<T: ?Sized> Rc<T> {
|
|||
/// mutate a shared value.
|
||||
///
|
||||
/// See also [`make_mut`][make_mut], which will [`clone`][clone]
|
||||
/// the inner value when there are other pointers.
|
||||
/// the inner value when there are other `Rc` pointers.
|
||||
///
|
||||
/// [make_mut]: Rc::make_mut
|
||||
/// [clone]: Clone::clone
|
||||
|
@ -1100,10 +1100,12 @@ impl<T: Clone> Rc<T> {
|
|||
/// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also
|
||||
/// referred to as clone-on-write.
|
||||
///
|
||||
/// If there are no other `Rc` pointers to this allocation, then [`Weak`]
|
||||
/// pointers to this allocation will be disassociated.
|
||||
/// However, if there are no other `Rc` pointers to this allocation, but some [`Weak`]
|
||||
/// pointers, then the [`Weak`] pointers will be disassociated and the inner value will not
|
||||
/// be cloned.
|
||||
///
|
||||
/// See also [`get_mut`], which will fail rather than cloning.
|
||||
/// See also [`get_mut`], which will fail rather than cloning the inner value
|
||||
/// or diassociating [`Weak`] pointers.
|
||||
///
|
||||
/// [`clone`]: Clone::clone
|
||||
/// [`get_mut`]: Rc::get_mut
|
||||
|
@ -1743,7 +1745,7 @@ impl<T: ?Sized> fmt::Pointer for Rc<T> {
|
|||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "from_for_ptrs", since = "1.6.0")]
|
||||
impl<T> From<T> for Rc<T> {
|
||||
/// Converts a generic type `T` into a `Rc<T>`
|
||||
/// Converts a generic type `T` into an `Rc<T>`
|
||||
///
|
||||
/// The conversion allocates on the heap and moves `t`
|
||||
/// from the stack into it.
|
||||
|
|
|
@ -1346,18 +1346,19 @@ impl<T: ?Sized> Receiver for Arc<T> {}
|
|||
impl<T: Clone> Arc<T> {
|
||||
/// Makes a mutable reference into the given `Arc`.
|
||||
///
|
||||
/// If there are other `Arc` or [`Weak`] pointers to the same allocation,
|
||||
/// then `make_mut` will create a new allocation and invoke [`clone`][clone] on the inner value
|
||||
/// to ensure unique ownership. This is also referred to as clone-on-write.
|
||||
/// If there are other `Arc` pointers to the same allocation, then `make_mut` will
|
||||
/// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also
|
||||
/// referred to as clone-on-write.
|
||||
///
|
||||
/// Note that this differs from the behavior of [`Rc::make_mut`] which disassociates
|
||||
/// any remaining `Weak` pointers.
|
||||
/// However, if there are no other `Arc` pointers to this allocation, but some [`Weak`]
|
||||
/// pointers, then the [`Weak`] pointers will be disassociated and the inner value will not
|
||||
/// be cloned.
|
||||
///
|
||||
/// See also [`get_mut`][get_mut], which will fail rather than cloning.
|
||||
/// See also [`get_mut`], which will fail rather than cloning the inner value
|
||||
/// or diassociating [`Weak`] pointers.
|
||||
///
|
||||
/// [clone]: Clone::clone
|
||||
/// [get_mut]: Arc::get_mut
|
||||
/// [`Rc::make_mut`]: super::rc::Rc::make_mut
|
||||
/// [`clone`]: Clone::clone
|
||||
/// [`get_mut`]: Arc::get_mut
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1376,6 +1377,23 @@ impl<T: Clone> Arc<T> {
|
|||
/// assert_eq!(*data, 8);
|
||||
/// assert_eq!(*other_data, 12);
|
||||
/// ```
|
||||
///
|
||||
/// [`Weak`] pointers will be disassociated:
|
||||
///
|
||||
/// ```
|
||||
/// use std::sync::Arc;
|
||||
///
|
||||
/// let mut data = Arc::new(75);
|
||||
/// let weak = Arc::downgrade(&data);
|
||||
///
|
||||
/// assert!(75 == *data);
|
||||
/// assert!(75 == *weak.upgrade().unwrap());
|
||||
///
|
||||
/// *Arc::make_mut(&mut data) += 1;
|
||||
///
|
||||
/// assert!(76 == *data);
|
||||
/// assert!(weak.upgrade().is_none());
|
||||
/// ```
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[inline]
|
||||
#[stable(feature = "arc_unique", since = "1.4.0")]
|
||||
|
@ -1441,7 +1459,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
/// mutate a shared value.
|
||||
///
|
||||
/// See also [`make_mut`][make_mut], which will [`clone`][clone]
|
||||
/// the inner value when there are other pointers.
|
||||
/// the inner value when there are other `Arc` pointers.
|
||||
///
|
||||
/// [make_mut]: Arc::make_mut
|
||||
/// [clone]: Clone::clone
|
||||
|
|
|
@ -35,11 +35,11 @@ fn box_clone_and_clone_from_equivalence() {
|
|||
}
|
||||
}
|
||||
|
||||
/// This test might give a false positive in case the box realocates, but the alocator keeps the
|
||||
/// original pointer.
|
||||
/// This test might give a false positive in case the box reallocates,
|
||||
/// but the allocator keeps the original pointer.
|
||||
///
|
||||
/// On the other hand it won't give a false negative, if it fails than the memory was definitely not
|
||||
/// reused
|
||||
/// On the other hand, it won't give a false negative: If it fails, then the
|
||||
/// memory was definitely not reused.
|
||||
#[test]
|
||||
fn box_clone_from_ptr_stability() {
|
||||
for size in (0..8).map(|i| 2usize.pow(i)) {
|
||||
|
|
|
@ -576,6 +576,26 @@ impl<T> Cell<[T]> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Cell<[T; N]> {
|
||||
/// Returns a `&[Cell<T>; N]` from a `&Cell<[T; N]>`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(as_array_of_cells)]
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let mut array: [i32; 3] = [1, 2, 3];
|
||||
/// let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array);
|
||||
/// let array_cell: &[Cell<i32>; 3] = cell_array.as_array_of_cells();
|
||||
/// ```
|
||||
#[unstable(feature = "as_array_of_cells", issue = "88248")]
|
||||
pub fn as_array_of_cells(&self) -> &[Cell<T>; N] {
|
||||
// SAFETY: `Cell<T>` has the same memory layout as `T`.
|
||||
unsafe { &*(self as *const Cell<[T; N]> as *const [Cell<T>; N]) }
|
||||
}
|
||||
}
|
||||
|
||||
/// A mutable memory location with dynamically checked borrow rules
|
||||
///
|
||||
/// See the [module-level documentation](self) for more.
|
||||
|
|
|
@ -1957,8 +1957,8 @@ pub trait Iterator {
|
|||
/// assert_eq!(it.next(), Some(&40));
|
||||
/// ```
|
||||
///
|
||||
/// While you cannot `break` from a closure, the [`crate::ops::ControlFlow`]
|
||||
/// type allows a similar idea:
|
||||
/// While you cannot `break` from a closure, the [`ControlFlow`] type allows
|
||||
/// a similar idea:
|
||||
///
|
||||
/// ```
|
||||
/// use std::ops::ControlFlow;
|
||||
|
@ -2024,8 +2024,8 @@ pub trait Iterator {
|
|||
/// assert_eq!(it.next(), Some("stale_bread.json"));
|
||||
/// ```
|
||||
///
|
||||
/// The [`crate::ops::ControlFlow`] type can be used with this method for the
|
||||
/// situations in which you'd use `break` and `continue` in a normal loop:
|
||||
/// The [`ControlFlow`] type can be used with this method for the situations
|
||||
/// in which you'd use `break` and `continue` in a normal loop:
|
||||
///
|
||||
/// ```
|
||||
/// use std::ops::ControlFlow;
|
||||
|
@ -2442,14 +2442,14 @@ pub trait Iterator {
|
|||
R: Try<Output = bool>,
|
||||
// FIXME: This bound is rather strange, but means minimal breakage on nightly.
|
||||
// See #85115 for the issue tracking a holistic solution for this and try_map.
|
||||
R: crate::ops::TryV2<Residual = Result<crate::convert::Infallible, E>>,
|
||||
R: Try<Residual = Result<crate::convert::Infallible, E>>,
|
||||
{
|
||||
#[inline]
|
||||
fn check<F, T, R, E>(mut f: F) -> impl FnMut((), T) -> ControlFlow<Result<T, E>>
|
||||
where
|
||||
F: FnMut(&T) -> R,
|
||||
R: Try<Output = bool>,
|
||||
R: crate::ops::TryV2<Residual = Result<crate::convert::Infallible, E>>,
|
||||
R: Try<Residual = Result<crate::convert::Infallible, E>>,
|
||||
{
|
||||
move |(), x| match f(&x).branch() {
|
||||
ControlFlow::Continue(false) => ControlFlow::CONTINUE,
|
||||
|
|
|
@ -63,7 +63,7 @@ pub enum ControlFlow<B, C = ()> {
|
|||
}
|
||||
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
impl<B, C> ops::TryV2 for ControlFlow<B, C> {
|
||||
impl<B, C> ops::Try for ControlFlow<B, C> {
|
||||
type Output = C;
|
||||
type Residual = ControlFlow<B, convert::Infallible>;
|
||||
|
||||
|
@ -165,7 +165,7 @@ impl<B, C> ControlFlow<B, C> {
|
|||
/// These are used only as part of implementing the iterator adapters.
|
||||
/// They have mediocre names and non-obvious semantics, so aren't
|
||||
/// currently on a path to potential stabilization.
|
||||
impl<R: ops::TryV2> ControlFlow<R, R::Output> {
|
||||
impl<R: ops::Try> ControlFlow<R, R::Output> {
|
||||
/// Create a `ControlFlow` from any type implementing `Try`.
|
||||
#[inline]
|
||||
pub(crate) fn from_try(r: R) -> Self {
|
||||
|
|
|
@ -182,13 +182,7 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
|
|||
pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
|
||||
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
pub use self::try_trait::FromResidual;
|
||||
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
pub use self::try_trait::Try;
|
||||
|
||||
#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
|
||||
pub(crate) use self::try_trait::Try as TryV2;
|
||||
pub use self::try_trait::{FromResidual, Try};
|
||||
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
pub use self::generator::{Generator, GeneratorState};
|
||||
|
|
|
@ -2013,7 +2013,7 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
|
|||
}
|
||||
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
impl<T> ops::TryV2 for Option<T> {
|
||||
impl<T> ops::Try for Option<T> {
|
||||
type Output = T;
|
||||
type Residual = Option<convert::Infallible>;
|
||||
|
||||
|
|
|
@ -1889,7 +1889,7 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
|
|||
}
|
||||
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
impl<T, E> ops::TryV2 for Result<T, E> {
|
||||
impl<T, E> ops::Try for Result<T, E> {
|
||||
type Output = T;
|
||||
type Residual = Result<convert::Infallible, E>;
|
||||
|
||||
|
|
|
@ -369,6 +369,22 @@ where
|
|||
// Instead of swapping one pair at the time, it is more efficient to perform a cyclic
|
||||
// permutation. This is not strictly equivalent to swapping, but produces a similar
|
||||
// result using fewer memory operations.
|
||||
|
||||
// SAFETY: The use of `ptr::read` is valid because there is at least one element in
|
||||
// both `offsets_l` and `offsets_r`, so `left!` is a valid pointer to read from.
|
||||
//
|
||||
// The uses of `left!` involve calls to `offset` on `l`, which points to the
|
||||
// beginning of `v`. All the offsets pointed-to by `start_l` are at most `block_l`, so
|
||||
// these `offset` calls are safe as all reads are within the block. The same argument
|
||||
// applies for the uses of `right!`.
|
||||
//
|
||||
// The calls to `start_l.offset` are valid because there are at most `count-1` of them,
|
||||
// plus the final one at the end of the unsafe block, where `count` is the minimum number
|
||||
// of collected offsets in `offsets_l` and `offsets_r`, so there is no risk of there not
|
||||
// being enough elements. The same reasoning applies to the calls to `start_r.offset`.
|
||||
//
|
||||
// The calls to `copy_nonoverlapping` are safe because `left!` and `right!` are guaranteed
|
||||
// not to overlap, and are valid because of the reasoning above.
|
||||
unsafe {
|
||||
let tmp = ptr::read(left!());
|
||||
ptr::copy_nonoverlapping(right!(), left!(), 1);
|
||||
|
@ -389,11 +405,21 @@ where
|
|||
|
||||
if start_l == end_l {
|
||||
// All out-of-order elements in the left block were moved. Move to the next block.
|
||||
|
||||
// block-width-guarantee
|
||||
// SAFETY: if `!is_done` then the slice width is guaranteed to be at least `2*BLOCK` wide. There
|
||||
// are at most `BLOCK` elements in `offsets_l` because of its size, so the `offset` operation is
|
||||
// safe. Otherwise, the debug assertions in the `is_done` case guarantee that
|
||||
// `width(l, r) == block_l + block_r`, namely, that the block sizes have been adjusted to account
|
||||
// for the smaller number of remaining elements.
|
||||
l = unsafe { l.offset(block_l as isize) };
|
||||
}
|
||||
|
||||
if start_r == end_r {
|
||||
// All out-of-order elements in the right block were moved. Move to the previous block.
|
||||
|
||||
// SAFETY: Same argument as [block-width-guarantee]. Either this is a full block `2*BLOCK`-wide,
|
||||
// or `block_r` has been adjusted for the last handful of elements.
|
||||
r = unsafe { r.offset(-(block_r as isize)) };
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ impl<T> From<T> for Poll<T> {
|
|||
}
|
||||
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
impl<T, E> ops::TryV2 for Poll<Result<T, E>> {
|
||||
impl<T, E> ops::Try for Poll<Result<T, E>> {
|
||||
type Output = Poll<T>;
|
||||
type Residual = Result<convert::Infallible, E>;
|
||||
|
||||
|
@ -252,7 +252,7 @@ impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Pol
|
|||
}
|
||||
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
impl<T, E> ops::TryV2 for Poll<Option<Result<T, E>>> {
|
||||
impl<T, E> ops::Try for Poll<Option<Result<T, E>>> {
|
||||
type Output = Poll<Option<T>>;
|
||||
type Residual = Result<convert::Infallible, E>;
|
||||
|
||||
|
|
|
@ -958,7 +958,7 @@ impl From<&CStr> for Arc<CStr> {
|
|||
|
||||
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
|
||||
impl From<CString> for Rc<CStr> {
|
||||
/// Converts a [`CString`] into a [`Rc`]`<CStr>` without copying or allocating.
|
||||
/// Converts a [`CString`] into an [`Rc`]`<CStr>` without copying or allocating.
|
||||
#[inline]
|
||||
fn from(s: CString) -> Rc<CStr> {
|
||||
let rc: Rc<[u8]> = Rc::from(s.into_inner());
|
||||
|
|
|
@ -916,7 +916,7 @@ impl From<&OsStr> for Arc<OsStr> {
|
|||
|
||||
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
|
||||
impl From<OsString> for Rc<OsStr> {
|
||||
/// Converts an [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
|
||||
/// Converts an [`OsString`] into an [`Rc`]`<OsStr>` without copying or allocating.
|
||||
#[inline]
|
||||
fn from(s: OsString) -> Rc<OsStr> {
|
||||
let rc = s.inner.into_rc();
|
||||
|
|
|
@ -323,7 +323,6 @@ impl<W: Write> BufWriter<W> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(bufwriter_into_parts)]
|
||||
/// use std::io::{BufWriter, Write};
|
||||
///
|
||||
/// let mut buffer = [0u8; 10];
|
||||
|
@ -334,7 +333,7 @@ impl<W: Write> BufWriter<W> {
|
|||
/// assert_eq!(recovered_writer.len(), 0);
|
||||
/// assert_eq!(&buffered_data.unwrap(), b"ata");
|
||||
/// ```
|
||||
#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
|
||||
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
|
||||
pub fn into_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
|
||||
let buf = mem::take(&mut self.buf);
|
||||
let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
|
||||
|
@ -444,14 +443,13 @@ impl<W: Write> BufWriter<W> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
|
||||
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
|
||||
/// Error returned for the buffered data from `BufWriter::into_parts`, when the underlying
|
||||
/// writer has previously panicked. Contains the (possibly partly written) buffered data.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(bufwriter_into_parts)]
|
||||
/// use std::io::{self, BufWriter, Write};
|
||||
/// use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
///
|
||||
|
@ -478,7 +476,7 @@ pub struct WriterPanicked {
|
|||
impl WriterPanicked {
|
||||
/// Returns the perhaps-unwritten data. Some of this data may have been written by the
|
||||
/// panicking call(s) to the underlying writer, so simply writing it again is not a good idea.
|
||||
#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
|
||||
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
|
||||
pub fn into_inner(self) -> Vec<u8> {
|
||||
self.buf
|
||||
}
|
||||
|
@ -487,7 +485,7 @@ impl WriterPanicked {
|
|||
"BufWriter inner writer panicked, what data remains unwritten is not known";
|
||||
}
|
||||
|
||||
#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
|
||||
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
|
||||
impl error::Error for WriterPanicked {
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
fn description(&self) -> &str {
|
||||
|
@ -495,14 +493,14 @@ impl error::Error for WriterPanicked {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
|
||||
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
|
||||
impl fmt::Display for WriterPanicked {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", Self::DESCRIPTION)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
|
||||
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
|
||||
impl fmt::Debug for WriterPanicked {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("WriterPanicked")
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::io::Error;
|
|||
|
||||
pub use bufreader::BufReader;
|
||||
pub use bufwriter::BufWriter;
|
||||
#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
|
||||
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
|
||||
pub use bufwriter::WriterPanicked;
|
||||
pub use linewriter::LineWriter;
|
||||
use linewritershim::LineWriterShim;
|
||||
|
|
|
@ -261,6 +261,33 @@ pub enum ErrorKind {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Interrupted,
|
||||
|
||||
/// This operation is unsupported on this platform.
|
||||
///
|
||||
/// This means that the operation can never succeed.
|
||||
#[stable(feature = "unsupported_error", since = "1.53.0")]
|
||||
Unsupported,
|
||||
|
||||
// ErrorKinds which are primarily categorisations for OS error
|
||||
// codes should be added above.
|
||||
//
|
||||
/// An error returned when an operation could not be completed because an
|
||||
/// "end of file" was reached prematurely.
|
||||
///
|
||||
/// This typically means that an operation could only succeed if it read a
|
||||
/// particular number of bytes but only a smaller number of bytes could be
|
||||
/// read.
|
||||
#[stable(feature = "read_exact", since = "1.6.0")]
|
||||
UnexpectedEof,
|
||||
|
||||
/// An operation could not be completed, because it failed
|
||||
/// to allocate enough memory.
|
||||
#[stable(feature = "out_of_memory_error", since = "1.54.0")]
|
||||
OutOfMemory,
|
||||
|
||||
// "Unusual" error kinds which do not correspond simply to (sets
|
||||
// of) OS error codes, should be added just above this comment.
|
||||
// `Other` and `Uncategorised` should remain at the end:
|
||||
//
|
||||
/// A custom error that does not fall under any other I/O error kind.
|
||||
///
|
||||
/// This can be used to construct your own [`Error`]s that do not match any
|
||||
|
@ -274,26 +301,6 @@ pub enum ErrorKind {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Other,
|
||||
|
||||
/// An error returned when an operation could not be completed because an
|
||||
/// "end of file" was reached prematurely.
|
||||
///
|
||||
/// This typically means that an operation could only succeed if it read a
|
||||
/// particular number of bytes but only a smaller number of bytes could be
|
||||
/// read.
|
||||
#[stable(feature = "read_exact", since = "1.6.0")]
|
||||
UnexpectedEof,
|
||||
|
||||
/// This operation is unsupported on this platform.
|
||||
///
|
||||
/// This means that the operation can never succeed.
|
||||
#[stable(feature = "unsupported_error", since = "1.53.0")]
|
||||
Unsupported,
|
||||
|
||||
/// An operation could not be completed, because it failed
|
||||
/// to allocate enough memory.
|
||||
#[stable(feature = "out_of_memory_error", since = "1.54.0")]
|
||||
OutOfMemory,
|
||||
|
||||
/// Any I/O error from the standard library that's not part of this list.
|
||||
///
|
||||
/// Errors that are `Uncategorized` now may move to a different or a new
|
||||
|
@ -307,13 +314,13 @@ pub enum ErrorKind {
|
|||
impl ErrorKind {
|
||||
pub(crate) fn as_str(&self) -> &'static str {
|
||||
use ErrorKind::*;
|
||||
// Strictly alphabetical, please. (Sadly rustfmt cannot do this yet.)
|
||||
match *self {
|
||||
AddrInUse => "address in use",
|
||||
AddrNotAvailable => "address not available",
|
||||
AlreadyExists => "entity already exists",
|
||||
ArgumentListTooLong => "argument list too long",
|
||||
BrokenPipe => "broken pipe",
|
||||
ResourceBusy => "resource busy",
|
||||
ConnectionAborted => "connection aborted",
|
||||
ConnectionRefused => "connection refused",
|
||||
ConnectionReset => "connection reset",
|
||||
|
@ -321,9 +328,10 @@ impl ErrorKind {
|
|||
Deadlock => "deadlock",
|
||||
DirectoryNotEmpty => "directory not empty",
|
||||
ExecutableFileBusy => "executable file busy",
|
||||
FilenameTooLong => "filename too long",
|
||||
FilesystemQuotaExceeded => "filesystem quota exceeded",
|
||||
FileTooLarge => "file too large",
|
||||
FilenameTooLong => "filename too long",
|
||||
FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
|
||||
FilesystemQuotaExceeded => "filesystem quota exceeded",
|
||||
HostUnreachable => "host unreachable",
|
||||
Interrupted => "operation interrupted",
|
||||
InvalidData => "invalid data",
|
||||
|
@ -332,16 +340,16 @@ impl ErrorKind {
|
|||
NetworkDown => "network down",
|
||||
NetworkUnreachable => "network unreachable",
|
||||
NotADirectory => "not a directory",
|
||||
StorageFull => "no storage space",
|
||||
NotConnected => "not connected",
|
||||
NotFound => "entity not found",
|
||||
NotSeekable => "seek on unseekable file",
|
||||
Other => "other error",
|
||||
OutOfMemory => "out of memory",
|
||||
PermissionDenied => "permission denied",
|
||||
ReadOnlyFilesystem => "read-only filesystem or storage medium",
|
||||
ResourceBusy => "resource busy",
|
||||
StaleNetworkFileHandle => "stale network file handle",
|
||||
FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
|
||||
NotSeekable => "seek on unseekable file",
|
||||
StorageFull => "no storage space",
|
||||
TimedOut => "timed out",
|
||||
TooManyLinks => "too many links",
|
||||
Uncategorized => "uncategorized error",
|
||||
|
|
|
@ -264,7 +264,7 @@ use crate::sys_common::memchr;
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::buffered::IntoInnerError;
|
||||
#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
|
||||
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
|
||||
pub use self::buffered::WriterPanicked;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::buffered::{BufReader, BufWriter, LineWriter};
|
||||
|
|
|
@ -301,6 +301,7 @@ def default_build_triple(verbose):
|
|||
'ppc': 'powerpc',
|
||||
'ppc64': 'powerpc64',
|
||||
'ppc64le': 'powerpc64le',
|
||||
'riscv64': 'riscv64gc',
|
||||
's390x': 's390x',
|
||||
'x64': 'x86_64',
|
||||
'x86': 'i686',
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7e49659102f0977d9142190e1ba23345c0f00eb1
|
||||
Subproject commit 687e21bde2ea10c261f79fa14797c5137425098d
|
|
@ -1 +1 @@
|
|||
Subproject commit 4884fe45c14f8b22121760fb117181bb4da8dfe0
|
||||
Subproject commit da6ea9b03f74cae0a292f40315723d7a3a973637
|
|
@ -1 +1 @@
|
|||
Subproject commit 0dc9cd4e89f00cb5230f120e1a083916386e422b
|
||||
Subproject commit 04f489c889235fe3b6dfe678ae5410d07deda958
|
|
@ -1 +1 @@
|
|||
Subproject commit c4644b427cbdaafc7a87be0ccdf5d8aaa07ac35f
|
||||
Subproject commit cf0e151b7925a40f13fbc6573c6f97d5f94c7c17
|
|
@ -1,6 +1,14 @@
|
|||
// only-x86_64
|
||||
|
||||
#![feature(asm, global_asm)]
|
||||
// Tests that the use of named labels in the `asm!` macro are linted against
|
||||
// except for in `#[naked]` fns.
|
||||
// Using a named label is incorrect as per the RFC because for most cases
|
||||
// the compiler cannot ensure that inline asm is emitted exactly once per
|
||||
// codegen unit (except for naked fns) and so the label could be duplicated
|
||||
// which causes less readable LLVM errors and in the worst cases causes ICEs
|
||||
// or segfaults based on system dependent behavior and codegen flags.
|
||||
|
||||
#![feature(asm, global_asm, naked_functions)]
|
||||
|
||||
#[no_mangle]
|
||||
pub static FOO: usize = 42;
|
||||
|
@ -126,5 +134,61 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
// Trigger on naked fns too, even though they can't be inlined, reusing a
|
||||
// label or LTO can cause labels to break
|
||||
#[naked]
|
||||
pub extern "C" fn foo() -> i32 {
|
||||
unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } //~ ERROR avoid using named labels
|
||||
}
|
||||
|
||||
// Make sure that non-naked attributes *do* still let the lint happen
|
||||
#[no_mangle]
|
||||
pub extern "C" fn bar() {
|
||||
unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
|
||||
//~^ ERROR avoid using named labels
|
||||
}
|
||||
|
||||
#[naked]
|
||||
pub extern "C" fn aaa() {
|
||||
fn _local() {}
|
||||
|
||||
unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels
|
||||
}
|
||||
|
||||
pub fn normal() {
|
||||
fn _local1() {}
|
||||
|
||||
#[naked]
|
||||
pub extern "C" fn bbb() {
|
||||
fn _very_local() {}
|
||||
|
||||
unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels
|
||||
}
|
||||
|
||||
fn _local2() {}
|
||||
}
|
||||
|
||||
// Make sure that the lint happens within closures
|
||||
fn closures() {
|
||||
|| unsafe {
|
||||
asm!("closure1: nop"); //~ ERROR avoid using named labels
|
||||
};
|
||||
|
||||
move || unsafe {
|
||||
asm!("closure2: nop"); //~ ERROR avoid using named labels
|
||||
};
|
||||
|
||||
|| {
|
||||
#[naked]
|
||||
unsafe extern "C" fn _nested() {
|
||||
asm!("ret;", options(noreturn));
|
||||
}
|
||||
|
||||
unsafe {
|
||||
asm!("closure3: nop"); //~ ERROR avoid using named labels
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Don't trigger on global asm
|
||||
global_asm!("aaaaaaaa: nop");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:11:15
|
||||
--> $DIR/named-asm-labels.rs:19:15
|
||||
|
|
||||
LL | asm!("bar: nop");
|
||||
| ^^^
|
||||
|
@ -9,7 +9,7 @@ LL | asm!("bar: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:14:15
|
||||
--> $DIR/named-asm-labels.rs:22:15
|
||||
|
|
||||
LL | asm!("abcd:");
|
||||
| ^^^^
|
||||
|
@ -18,7 +18,7 @@ LL | asm!("abcd:");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:17:15
|
||||
--> $DIR/named-asm-labels.rs:25:15
|
||||
|
|
||||
LL | asm!("foo: bar1: nop");
|
||||
| ^^^ ^^^^
|
||||
|
@ -27,7 +27,7 @@ LL | asm!("foo: bar1: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:21:15
|
||||
--> $DIR/named-asm-labels.rs:29:15
|
||||
|
|
||||
LL | asm!("foo1: nop", "nop");
|
||||
| ^^^^
|
||||
|
@ -36,7 +36,7 @@ LL | asm!("foo1: nop", "nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:22:15
|
||||
--> $DIR/named-asm-labels.rs:30:15
|
||||
|
|
||||
LL | asm!("foo2: foo3: nop", "nop");
|
||||
| ^^^^ ^^^^
|
||||
|
@ -45,7 +45,7 @@ LL | asm!("foo2: foo3: nop", "nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:24:22
|
||||
--> $DIR/named-asm-labels.rs:32:22
|
||||
|
|
||||
LL | asm!("nop", "foo4: nop");
|
||||
| ^^^^
|
||||
|
@ -54,7 +54,7 @@ LL | asm!("nop", "foo4: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:25:15
|
||||
--> $DIR/named-asm-labels.rs:33:15
|
||||
|
|
||||
LL | asm!("foo5: nop", "foo6: nop");
|
||||
| ^^^^
|
||||
|
@ -63,7 +63,7 @@ LL | asm!("foo5: nop", "foo6: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:25:28
|
||||
--> $DIR/named-asm-labels.rs:33:28
|
||||
|
|
||||
LL | asm!("foo5: nop", "foo6: nop");
|
||||
| ^^^^
|
||||
|
@ -72,7 +72,7 @@ LL | asm!("foo5: nop", "foo6: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:30:15
|
||||
--> $DIR/named-asm-labels.rs:38:15
|
||||
|
|
||||
LL | asm!("foo7: nop; foo8: nop");
|
||||
| ^^^^ ^^^^
|
||||
|
@ -81,7 +81,7 @@ LL | asm!("foo7: nop; foo8: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:32:15
|
||||
--> $DIR/named-asm-labels.rs:40:15
|
||||
|
|
||||
LL | asm!("foo9: nop; nop");
|
||||
| ^^^^
|
||||
|
@ -90,7 +90,7 @@ LL | asm!("foo9: nop; nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:33:20
|
||||
--> $DIR/named-asm-labels.rs:41:20
|
||||
|
|
||||
LL | asm!("nop; foo10: nop");
|
||||
| ^^^^^
|
||||
|
@ -99,7 +99,7 @@ LL | asm!("nop; foo10: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:36:15
|
||||
--> $DIR/named-asm-labels.rs:44:15
|
||||
|
|
||||
LL | asm!("bar2: nop\n bar3: nop");
|
||||
| ^^^^ ^^^^
|
||||
|
@ -108,7 +108,7 @@ LL | asm!("bar2: nop\n bar3: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:38:15
|
||||
--> $DIR/named-asm-labels.rs:46:15
|
||||
|
|
||||
LL | asm!("bar4: nop\n nop");
|
||||
| ^^^^
|
||||
|
@ -117,7 +117,7 @@ LL | asm!("bar4: nop\n nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:39:21
|
||||
--> $DIR/named-asm-labels.rs:47:21
|
||||
|
|
||||
LL | asm!("nop\n bar5: nop");
|
||||
| ^^^^
|
||||
|
@ -126,7 +126,7 @@ LL | asm!("nop\n bar5: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:40:21
|
||||
--> $DIR/named-asm-labels.rs:48:21
|
||||
|
|
||||
LL | asm!("nop\n bar6: bar7: nop");
|
||||
| ^^^^ ^^^^
|
||||
|
@ -135,7 +135,7 @@ LL | asm!("nop\n bar6: bar7: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:46:13
|
||||
--> $DIR/named-asm-labels.rs:54:13
|
||||
|
|
||||
LL | blah2: nop
|
||||
| ^^^^^
|
||||
|
@ -146,7 +146,7 @@ LL | blah3: nop
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:55:19
|
||||
--> $DIR/named-asm-labels.rs:63:19
|
||||
|
|
||||
LL | nop ; blah4: nop
|
||||
| ^^^^^
|
||||
|
@ -155,7 +155,7 @@ LL | nop ; blah4: nop
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:69:15
|
||||
--> $DIR/named-asm-labels.rs:77:15
|
||||
|
|
||||
LL | asm!("blah1: 2bar: nop");
|
||||
| ^^^^^
|
||||
|
@ -164,7 +164,7 @@ LL | asm!("blah1: 2bar: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:72:15
|
||||
--> $DIR/named-asm-labels.rs:80:15
|
||||
|
|
||||
LL | asm!("def: def: nop");
|
||||
| ^^^
|
||||
|
@ -173,7 +173,7 @@ LL | asm!("def: def: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:73:15
|
||||
--> $DIR/named-asm-labels.rs:81:15
|
||||
|
|
||||
LL | asm!("def: nop\ndef: nop");
|
||||
| ^^^
|
||||
|
@ -182,7 +182,7 @@ LL | asm!("def: nop\ndef: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:74:15
|
||||
--> $DIR/named-asm-labels.rs:82:15
|
||||
|
|
||||
LL | asm!("def: nop; def: nop");
|
||||
| ^^^
|
||||
|
@ -191,7 +191,7 @@ LL | asm!("def: nop; def: nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:82:15
|
||||
--> $DIR/named-asm-labels.rs:90:15
|
||||
|
|
||||
LL | asm!("fooo\u{003A} nop");
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
@ -200,7 +200,7 @@ LL | asm!("fooo\u{003A} nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:83:15
|
||||
--> $DIR/named-asm-labels.rs:91:15
|
||||
|
|
||||
LL | asm!("foooo\x3A nop");
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -209,7 +209,7 @@ LL | asm!("foooo\x3A nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:86:15
|
||||
--> $DIR/named-asm-labels.rs:94:15
|
||||
|
|
||||
LL | asm!("fooooo:\u{000A} nop");
|
||||
| ^^^^^^
|
||||
|
@ -218,7 +218,7 @@ LL | asm!("fooooo:\u{000A} nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:87:15
|
||||
--> $DIR/named-asm-labels.rs:95:15
|
||||
|
|
||||
LL | asm!("foooooo:\x0A nop");
|
||||
| ^^^^^^^
|
||||
|
@ -227,7 +227,7 @@ LL | asm!("foooooo:\x0A nop");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:91:14
|
||||
--> $DIR/named-asm-labels.rs:99:14
|
||||
|
|
||||
LL | asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -236,7 +236,7 @@ LL | asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70");
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:102:13
|
||||
--> $DIR/named-asm-labels.rs:110:13
|
||||
|
|
||||
LL | ab: nop // ab: does foo
|
||||
| ^^
|
||||
|
@ -245,7 +245,7 @@ LL | ab: nop // ab: does foo
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:114:14
|
||||
--> $DIR/named-asm-labels.rs:122:14
|
||||
|
|
||||
LL | asm!(include_str!("named-asm-labels.s"));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -254,18 +254,81 @@ LL | asm!(include_str!("named-asm-labels.s"));
|
|||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
warning: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:124:19
|
||||
--> $DIR/named-asm-labels.rs:132:19
|
||||
|
|
||||
LL | asm!("warned: nop");
|
||||
| ^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/named-asm-labels.rs:122:16
|
||||
--> $DIR/named-asm-labels.rs:130:16
|
||||
|
|
||||
LL | #[warn(named_asm_labels)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= help: only local labels of the form `<number>:` should be used in inline asm
|
||||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: aborting due to 28 previous errors; 1 warning emitted
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:141:20
|
||||
|
|
||||
LL | unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
|
||||
| ^^^^^
|
||||
|
|
||||
= help: only local labels of the form `<number>:` should be used in inline asm
|
||||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:147:20
|
||||
|
|
||||
LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
|
||||
| ^^^^^
|
||||
|
|
||||
= help: only local labels of the form `<number>:` should be used in inline asm
|
||||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:155:20
|
||||
|
|
||||
LL | unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) }
|
||||
| ^^^^^
|
||||
|
|
||||
= help: only local labels of the form `<number>:` should be used in inline asm
|
||||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:165:24
|
||||
|
|
||||
LL | unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) }
|
||||
| ^^^^^
|
||||
|
|
||||
= help: only local labels of the form `<number>:` should be used in inline asm
|
||||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:174:15
|
||||
|
|
||||
LL | asm!("closure1: nop");
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= help: only local labels of the form `<number>:` should be used in inline asm
|
||||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:178:15
|
||||
|
|
||||
LL | asm!("closure2: nop");
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= help: only local labels of the form `<number>:` should be used in inline asm
|
||||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: avoid using named labels in inline assembly
|
||||
--> $DIR/named-asm-labels.rs:188:19
|
||||
|
|
||||
LL | asm!("closure3: nop");
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= help: only local labels of the form `<number>:` should be used in inline asm
|
||||
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
|
||||
|
||||
error: aborting due to 35 previous errors; 1 warning emitted
|
||||
|
||||
|
|
|
@ -368,7 +368,7 @@ pub fn main() {
|
|||
// We can use refcells if we're single-threaded (as this test is).
|
||||
// If one were to generalize these constructions to a
|
||||
// multi-threaded context, then it might seem like we could choose
|
||||
// between either a RwLock or a Mutex to hold the owned arcs on
|
||||
// between either an RwLock or a Mutex to hold the owned arcs on
|
||||
// each node.
|
||||
//
|
||||
// Part of the point of this test is to actually confirm that the
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(as_array_of_cells)]
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
fn main() {
|
||||
|
@ -8,4 +10,11 @@ fn main() {
|
|||
let slice_cell: &[Cell<i32>] = cell_slice.as_slice_of_cells();
|
||||
|
||||
assert_eq!(slice_cell.len(), 3);
|
||||
|
||||
let mut array: [i32; 3] = [1, 2, 3];
|
||||
let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array);
|
||||
let array_cell: &[Cell<i32>; 3] = cell_array.as_array_of_cells();
|
||||
|
||||
array_cell[0].set(99);
|
||||
assert_eq!(array, [99, 2, 3]);
|
||||
}
|
||||
|
|
29
src/test/ui/type-alias-impl-trait/type_of_a_let.rs
Normal file
29
src/test/ui/type-alias-impl-trait/type_of_a_let.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
// FIXME This should compile, but it currently doesn't
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
type Foo = impl Debug;
|
||||
//~^ ERROR: could not find defining uses
|
||||
|
||||
fn foo1() -> u32 {
|
||||
let x: Foo = 22_u32;
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
x
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
}
|
||||
|
||||
fn foo2() -> u32 {
|
||||
let x: Foo = 22_u32;
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
let y: Foo = x;
|
||||
same_type((x, y));
|
||||
y
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
}
|
||||
|
||||
fn same_type<T>(x: (T, T)) {}
|
||||
|
||||
fn main() {}
|
67
src/test/ui/type-alias-impl-trait/type_of_a_let.stderr
Normal file
67
src/test/ui/type-alias-impl-trait/type_of_a_let.stderr
Normal file
|
@ -0,0 +1,67 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/type_of_a_let.rs:12:18
|
||||
|
|
||||
LL | type Foo = impl Debug;
|
||||
| ---------- the expected opaque type
|
||||
...
|
||||
LL | let x: Foo = 22_u32;
|
||||
| --- ^^^^^^ expected opaque type, found `u32`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected opaque type `impl Debug`
|
||||
found type `u32`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_of_a_let.rs:14:5
|
||||
|
|
||||
LL | type Foo = impl Debug;
|
||||
| ---------- the found opaque type
|
||||
...
|
||||
LL | fn foo1() -> u32 {
|
||||
| --- expected `u32` because of return type
|
||||
...
|
||||
LL | x
|
||||
| ^ expected `u32`, found opaque type
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found opaque type `impl Debug`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_of_a_let.rs:19:18
|
||||
|
|
||||
LL | type Foo = impl Debug;
|
||||
| ---------- the expected opaque type
|
||||
...
|
||||
LL | let x: Foo = 22_u32;
|
||||
| --- ^^^^^^ expected opaque type, found `u32`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected opaque type `impl Debug`
|
||||
found type `u32`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_of_a_let.rs:23:5
|
||||
|
|
||||
LL | type Foo = impl Debug;
|
||||
| ---------- the found opaque type
|
||||
...
|
||||
LL | fn foo2() -> u32 {
|
||||
| --- expected `u32` because of return type
|
||||
...
|
||||
LL | y
|
||||
| ^ expected `u32`, found opaque type
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found opaque type `impl Debug`
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/type_of_a_let.rs:8:12
|
||||
|
|
||||
LL | type Foo = impl Debug;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
25
src/test/ui/type-alias-impl-trait/type_of_a_let2.rs
Normal file
25
src/test/ui/type-alias-impl-trait/type_of_a_let2.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
// FIXME This should be under a feature flag
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
fn foo1() -> u32 {
|
||||
let x: impl Debug = 22_u32;
|
||||
//~^ ERROR: `impl Trait` not allowed outside of function and method return types [E0562]
|
||||
x // ERROR: we only know x: Debug, we don't know x = u32
|
||||
}
|
||||
|
||||
fn foo2() -> u32 {
|
||||
let x: impl Debug = 22_u32;
|
||||
//~^ ERROR: `impl Trait` not allowed outside of function and method return types [E0562]
|
||||
let y: impl Debug = x;
|
||||
//~^ ERROR: `impl Trait` not allowed outside of function and method return types [E0562]
|
||||
same_type((x, y)); // ERROR
|
||||
x
|
||||
}
|
||||
|
||||
fn same_type<T>(x: (T, T)) {}
|
||||
|
||||
fn main() {}
|
21
src/test/ui/type-alias-impl-trait/type_of_a_let2.stderr
Normal file
21
src/test/ui/type-alias-impl-trait/type_of_a_let2.stderr
Normal file
|
@ -0,0 +1,21 @@
|
|||
error[E0562]: `impl Trait` not allowed outside of function and method return types
|
||||
--> $DIR/type_of_a_let2.rs:9:12
|
||||
|
|
||||
LL | let x: impl Debug = 22_u32;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and method return types
|
||||
--> $DIR/type_of_a_let2.rs:15:12
|
||||
|
|
||||
LL | let x: impl Debug = 22_u32;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and method return types
|
||||
--> $DIR/type_of_a_let2.rs:17:12
|
||||
|
|
||||
LL | let y: impl Debug = x;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0562`.
|
Loading…
Add table
Add a link
Reference in a new issue