mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #100793 - matthiaskrgr:rollup-dy7rfdh, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #100186 (Mention `as_mut` alongside `as_ref` in borrowck error message) - #100383 (Mitigate stale data reads on SGX platform) - #100507 (suggest `once_cell::Lazy` for non-const statics) - #100617 (Suggest the right help message for as_ref) - #100667 (Migrate "invalid variable declaration" errors to SessionDiagnostic) - #100709 (Migrate typeck's `used` expected symbol diagnostic to `SessionDiagnostic`) - #100723 (Add the diagnostic translation lints to crates that don't emit them) - #100729 (Avoid zeroing a 1kb stack buffer on every call to `std::sys::windows::fill_utf16_buf`) - #100750 (improved diagnostic for function defined with `def`, `fun`, `func`, or `function` instead of `fn`) - #100763 (triagebot: Autolabel `A-rustdoc-json`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
36e530cb08
@ -33,6 +33,8 @@
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![no_std]
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate alloc;
|
||||
|
@ -19,6 +19,8 @@
|
||||
#![feature(rustc_attrs)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
#![feature(strict_provenance)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
#![feature(slice_internals)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![recursion_limit = "256"]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
@ -1,3 +1,5 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(with_negative_coherence)]
|
||||
|
@ -1086,14 +1086,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
),
|
||||
);
|
||||
}
|
||||
if is_option_or_result && maybe_reinitialized_locations_is_empty {
|
||||
err.span_suggestion_verbose(
|
||||
fn_call_span.shrink_to_lo(),
|
||||
"consider calling `.as_ref()` to borrow the type's contents",
|
||||
"as_ref().",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
// Avoid pointing to the same function in multiple different
|
||||
// error messages.
|
||||
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
|
||||
@ -1102,6 +1094,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&format!("this function takes ownership of the receiver `self`, which moves {}", place_name)
|
||||
);
|
||||
}
|
||||
if is_option_or_result && maybe_reinitialized_locations_is_empty {
|
||||
err.span_label(
|
||||
var_span,
|
||||
"help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents",
|
||||
);
|
||||
}
|
||||
}
|
||||
// Other desugarings takes &self, which cannot cause a move
|
||||
_ => {}
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Concrete error types for all operations which may be invalid in a certain const context.
|
||||
|
||||
use hir::def_id::LocalDefId;
|
||||
use hir::ConstContext;
|
||||
use rustc_errors::{
|
||||
error_code, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed,
|
||||
};
|
||||
@ -331,6 +332,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
||||
ccx.const_kind(),
|
||||
));
|
||||
|
||||
if let ConstContext::Static(_) = ccx.const_kind() {
|
||||
err.note("consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell");
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,8 @@
|
||||
#![feature(vec_into_raw_parts)]
|
||||
#![allow(rustc::default_hash_types)]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
@ -1,4 +1,6 @@
|
||||
#![deny(rustdoc::invalid_codeblock_attributes)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
//! This library is used to gather all error codes into one place,
|
||||
//! the goal being to make their maintenance easier.
|
||||
|
||||
|
@ -32,3 +32,12 @@ parser_incorrect_use_of_await =
|
||||
parser_in_in_typo =
|
||||
expected iterable, found keyword `in`
|
||||
.suggestion = remove the duplicated `in`
|
||||
|
||||
parser_invalid_variable_declaration =
|
||||
invalid variable declaration
|
||||
|
||||
parser_switch_mut_let_order =
|
||||
switch the order of `mut` and `let`
|
||||
parser_missing_let_before_mut = missing keyword
|
||||
parser_use_let_not_auto = write `let` instead of `auto` to introduce a new variable
|
||||
parser_use_let_not_var = write `let` instead of `var` to introduce a new variable
|
||||
|
@ -131,3 +131,5 @@ typeck_unused_extern_crate =
|
||||
typeck_extern_crate_not_idiomatic =
|
||||
`extern crate` is not idiomatic in the new edition
|
||||
.suggestion = convert it to a `{$msg_code}`
|
||||
|
||||
typeck_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
|
||||
|
@ -1,6 +1,8 @@
|
||||
#![feature(once_cell)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use fluent_bundle::FluentResource;
|
||||
use fluent_syntax::parser::ParserError;
|
||||
|
@ -12,6 +12,8 @@
|
||||
//! symbol to the `accepted` or `removed` modules respectively.
|
||||
|
||||
#![feature(once_cell)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
mod accepted;
|
||||
mod active;
|
||||
|
@ -1,3 +1,6 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
|
@ -273,6 +273,8 @@
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
||||
test(attr(allow(unused_variables), deny(warnings)))
|
||||
)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use LabelText::*;
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![recursion_limit = "256"]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
@ -1,4 +1,6 @@
|
||||
#![recursion_limit = "256"]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::util::parser::{self, AssocOp, Fixity};
|
||||
|
@ -1,3 +1,5 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![feature(allow_internal_unstable)]
|
||||
#![feature(bench_black_box)]
|
||||
#![feature(extend_one)]
|
||||
|
@ -2079,7 +2079,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
*msg,
|
||||
format!("{}.as_ref()", snippet),
|
||||
// HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
|
||||
format!("{}.as_ref()", snippet.trim_start_matches('&')),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
@ -18,6 +18,8 @@
|
||||
//! lexeme types.
|
||||
//!
|
||||
//! [`rustc_parse::lexer`]: ../rustc_parse/lexer/index.html
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
// We want to be able to build this crate with a stable compiler, so no
|
||||
// `#![feature]` attributes should be added.
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
#![feature(min_specialization)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
@ -1,3 +1,5 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
|
||||
// NOTE: This crate only exists to allow linking on mingw targets.
|
||||
|
@ -38,6 +38,9 @@
|
||||
//! debugging, you can make changes inside those crates and quickly run main.rs
|
||||
//! to read the debug logs.
|
||||
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use std::env::{self, VarError};
|
||||
use std::fmt::{self, Display};
|
||||
use std::io;
|
||||
|
@ -4,6 +4,8 @@
|
||||
#![feature(proc_macro_diagnostic)]
|
||||
#![feature(proc_macro_span)]
|
||||
#![allow(rustc::default_hash_types)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![recursion_limit = "128"]
|
||||
|
||||
use synstructure::decl_derive;
|
||||
|
@ -334,6 +334,35 @@ struct InInTypo {
|
||||
sugg_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error(parser::invalid_variable_declaration)]
|
||||
pub struct InvalidVariableDeclaration {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub sub: InvalidVariableDeclarationSub,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub enum InvalidVariableDeclarationSub {
|
||||
#[suggestion(
|
||||
parser::switch_mut_let_order,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "let mut"
|
||||
)]
|
||||
SwitchMutLetOrder(#[primary_span] Span),
|
||||
#[suggestion(
|
||||
parser::missing_let_before_mut,
|
||||
applicability = "machine-applicable",
|
||||
code = "let mut"
|
||||
)]
|
||||
MissingLet(#[primary_span] Span),
|
||||
#[suggestion(parser::use_let_not_auto, applicability = "machine-applicable", code = "let")]
|
||||
UseLetNotAuto(#[primary_span] Span),
|
||||
#[suggestion(parser::use_let_not_var, applicability = "machine-applicable", code = "let")]
|
||||
UseLetNotVar(#[primary_span] Span),
|
||||
}
|
||||
|
||||
// SnapshotParser is used to create a snapshot of the parser
|
||||
// without causing duplicate errors being emitted when the `Parser`
|
||||
// is dropped.
|
||||
@ -611,6 +640,15 @@ impl<'a> Parser<'a> {
|
||||
appl,
|
||||
);
|
||||
}
|
||||
|
||||
if ["def", "fun", "func", "function"].contains(&symbol.as_str()) {
|
||||
err.span_suggestion_short(
|
||||
self.prev_token.span,
|
||||
&format!("write `fn` instead of `{symbol}` to declare a function"),
|
||||
"fn",
|
||||
appl,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add suggestion for a missing closing angle bracket if '>' is included in expected_tokens
|
||||
|
@ -1,5 +1,7 @@
|
||||
use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN;
|
||||
use super::diagnostics::{AttemptLocalParseRecovery, Error};
|
||||
use super::diagnostics::{
|
||||
AttemptLocalParseRecovery, Error, InvalidVariableDeclaration, InvalidVariableDeclarationSub,
|
||||
};
|
||||
use super::expr::LhsExpr;
|
||||
use super::pat::RecoverComma;
|
||||
use super::path::PathStyle;
|
||||
@ -58,28 +60,22 @@ impl<'a> Parser<'a> {
|
||||
if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) {
|
||||
self.bump();
|
||||
let mut_let_span = lo.to(self.token.span);
|
||||
self.struct_span_err(mut_let_span, "invalid variable declaration")
|
||||
.span_suggestion(
|
||||
mut_let_span,
|
||||
"switch the order of `mut` and `let`",
|
||||
"let mut",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidVariableDeclaration {
|
||||
span: mut_let_span,
|
||||
sub: InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Some(if self.token.is_keyword(kw::Let) {
|
||||
self.parse_local_mk(lo, attrs, capture_semi, force_collect)?
|
||||
} else if self.is_kw_followed_by_ident(kw::Mut) {
|
||||
self.recover_stmt_local(lo, attrs, "missing keyword", "let mut")?
|
||||
self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::MissingLet)?
|
||||
} else if self.is_kw_followed_by_ident(kw::Auto) {
|
||||
self.bump(); // `auto`
|
||||
let msg = "write `let` instead of `auto` to introduce a new variable";
|
||||
self.recover_stmt_local(lo, attrs, msg, "let")?
|
||||
self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::UseLetNotAuto)?
|
||||
} else if self.is_kw_followed_by_ident(sym::var) {
|
||||
self.bump(); // `var`
|
||||
let msg = "write `let` instead of `var` to introduce a new variable";
|
||||
self.recover_stmt_local(lo, attrs, msg, "let")?
|
||||
self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::UseLetNotVar)?
|
||||
} else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() {
|
||||
// We have avoided contextual keywords like `union`, items with `crate` visibility,
|
||||
// or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
|
||||
@ -217,13 +213,10 @@ impl<'a> Parser<'a> {
|
||||
&mut self,
|
||||
lo: Span,
|
||||
attrs: AttrWrapper,
|
||||
msg: &str,
|
||||
sugg: &str,
|
||||
subdiagnostic: fn(Span) -> InvalidVariableDeclarationSub,
|
||||
) -> PResult<'a, Stmt> {
|
||||
let stmt = self.recover_local_after_let(lo, attrs)?;
|
||||
self.struct_span_err(lo, "invalid variable declaration")
|
||||
.span_suggestion(lo, msg, sugg, Applicability::MachineApplicable)
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
|
||||
Ok(stmt)
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
html_playground_url = "https://play.rust-lang.org/",
|
||||
test(attr(deny(warnings)))
|
||||
)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
// We want to be able to build this crate with a stable compiler, so no
|
||||
// `#![feature]` attributes should be added.
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
#![feature(rustc_attrs)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
@ -18,6 +18,8 @@ Core encoding and decoding interfaces.
|
||||
#![feature(new_uninit)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
#![allow(rustc::internal)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
pub use self::serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
test(attr(allow(unused_variables), deny(warnings)))
|
||||
)]
|
||||
#![cfg_attr(not(feature = "default"), feature(rustc_private))]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
pub mod mir;
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
#![feature(negative_impls)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
@ -16,6 +16,8 @@
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(step_trait)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use std::iter::FromIterator;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -1,6 +1,8 @@
|
||||
//! New recursive solver modeled on Chalk's recursive solver. Most of
|
||||
//! the guts are broken up into modules; see the comments in those modules.
|
||||
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![feature(let_else)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
|
@ -2836,12 +2836,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
|
||||
}
|
||||
Some(_) => {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
attr.span,
|
||||
"expected `used`, `used(compiler)` or `used(linker)`",
|
||||
)
|
||||
.emit();
|
||||
tcx.sess.emit_err(errors::ExpectedUsedSymbol { span: attr.span });
|
||||
}
|
||||
None => {
|
||||
// Unfortunately, unconditionally using `llvm.used` causes
|
||||
|
@ -340,3 +340,10 @@ pub struct ExternCrateNotIdiomatic {
|
||||
pub msg_code: String,
|
||||
pub suggestion_code: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error(typeck::expected_used_symbol)]
|
||||
pub struct ExpectedUsedSymbol {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
@ -305,6 +305,34 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// Split a memory region ptr..ptr + len into three parts:
|
||||
// +--------+
|
||||
// | small0 | Chunk smaller than 8 bytes
|
||||
// +--------+
|
||||
// | big | Chunk 8-byte aligned, and size a multiple of 8 bytes
|
||||
// +--------+
|
||||
// | small1 | Chunk smaller than 8 bytes
|
||||
// +--------+
|
||||
fn region_as_aligned_chunks(ptr: *const u8, len: usize) -> (usize, usize, usize) {
|
||||
let small0_size = if ptr as usize % 8 == 0 { 0 } else { 8 - ptr as usize % 8 };
|
||||
let small1_size = (len - small0_size as usize) % 8;
|
||||
let big_size = len - small0_size as usize - small1_size as usize;
|
||||
|
||||
(small0_size, big_size, small1_size)
|
||||
}
|
||||
|
||||
unsafe fn copy_quadwords(src: *const u8, dst: *mut u8, len: usize) {
|
||||
unsafe {
|
||||
asm!(
|
||||
"rep movsq (%rsi), (%rdi)",
|
||||
inout("rcx") len / 8 => _,
|
||||
inout("rdi") dst => _,
|
||||
inout("rsi") src => _,
|
||||
options(att_syntax, nostack, preserves_flags)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies `len` bytes of data from enclave pointer `src` to userspace `dst`
|
||||
///
|
||||
/// This function mitigates stale data vulnerabilities by ensuring all writes to untrusted memory are either:
|
||||
@ -343,17 +371,6 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn copy_aligned_quadwords_to_userspace(src: *const u8, dst: *mut u8, len: usize) {
|
||||
unsafe {
|
||||
asm!(
|
||||
"rep movsq (%rsi), (%rdi)",
|
||||
inout("rcx") len / 8 => _,
|
||||
inout("rdi") dst => _,
|
||||
inout("rsi") src => _,
|
||||
options(att_syntax, nostack, preserves_flags)
|
||||
);
|
||||
}
|
||||
}
|
||||
assert!(!src.is_null());
|
||||
assert!(!dst.is_null());
|
||||
assert!(is_enclave_range(src, len));
|
||||
@ -370,7 +387,7 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
|
||||
} else if len % 8 == 0 && dst as usize % 8 == 0 {
|
||||
// Copying 8-byte aligned quadwords: copy quad word per quad word
|
||||
unsafe {
|
||||
copy_aligned_quadwords_to_userspace(src, dst, len);
|
||||
copy_quadwords(src, dst, len);
|
||||
}
|
||||
} else {
|
||||
// Split copies into three parts:
|
||||
@ -381,20 +398,16 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
|
||||
// +--------+
|
||||
// | small1 | Chunk smaller than 8 bytes
|
||||
// +--------+
|
||||
let (small0_size, big_size, small1_size) = region_as_aligned_chunks(dst, len);
|
||||
|
||||
unsafe {
|
||||
// Copy small0
|
||||
let small0_size = (8 - dst as usize % 8) as u8;
|
||||
let small0_src = src;
|
||||
let small0_dst = dst;
|
||||
copy_bytewise_to_userspace(small0_src as _, small0_dst, small0_size as _);
|
||||
copy_bytewise_to_userspace(src, dst, small0_size as _);
|
||||
|
||||
// Copy big
|
||||
let small1_size = ((len - small0_size as usize) % 8) as u8;
|
||||
let big_size = len - small0_size as usize - small1_size as usize;
|
||||
let big_src = src.offset(small0_size as _);
|
||||
let big_dst = dst.offset(small0_size as _);
|
||||
copy_aligned_quadwords_to_userspace(big_src as _, big_dst, big_size);
|
||||
copy_quadwords(big_src as _, big_dst, big_size);
|
||||
|
||||
// Copy small1
|
||||
let small1_src = src.offset(big_size as isize + small0_size as isize);
|
||||
@ -404,6 +417,106 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies `len` bytes of data from userspace pointer `src` to enclave pointer `dst`
|
||||
///
|
||||
/// This function mitigates AEPIC leak vulnerabilities by ensuring all reads from untrusted memory are 8-byte aligned
|
||||
///
|
||||
/// # Panics
|
||||
/// This function panics if:
|
||||
///
|
||||
/// * The `src` pointer is null
|
||||
/// * The `dst` pointer is null
|
||||
/// * The `src` memory range is not in user memory
|
||||
/// * The `dst` memory range is not in enclave memory
|
||||
///
|
||||
/// # References
|
||||
/// - https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00657.html
|
||||
/// - https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/stale-data-read-from-xapic.html
|
||||
pub(crate) unsafe fn copy_from_userspace(src: *const u8, dst: *mut u8, len: usize) {
|
||||
// Copies memory region `src..src + len` to the enclave at `dst`. The source memory region
|
||||
// is:
|
||||
// - strictly less than 8 bytes in size and may be
|
||||
// - located at a misaligned memory location
|
||||
fn copy_misaligned_chunk_to_enclave(src: *const u8, dst: *mut u8, len: usize) {
|
||||
let mut tmp_buff = [0u8; 16];
|
||||
|
||||
unsafe {
|
||||
// Compute an aligned memory region to read from
|
||||
// +--------+ <-- aligned_src + aligned_len (8B-aligned)
|
||||
// | pad1 |
|
||||
// +--------+ <-- src + len (misaligned)
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// +--------+ <-- src (misaligned)
|
||||
// | pad0 |
|
||||
// +--------+ <-- aligned_src (8B-aligned)
|
||||
let pad0_size = src as usize % 8;
|
||||
let aligned_src = src.sub(pad0_size);
|
||||
|
||||
let pad1_size = 8 - (src.add(len) as usize % 8);
|
||||
let aligned_len = pad0_size + len + pad1_size;
|
||||
|
||||
debug_assert!(len < 8);
|
||||
debug_assert_eq!(aligned_src as usize % 8, 0);
|
||||
debug_assert_eq!(aligned_len % 8, 0);
|
||||
debug_assert!(aligned_len <= 16);
|
||||
|
||||
// Copy the aligned buffer to a temporary buffer
|
||||
// Note: copying from a slightly different memory location is a bit odd. In this case it
|
||||
// can't lead to page faults or inadvertent copying from the enclave as we only ensured
|
||||
// that the `src` pointer is aligned at an 8 byte boundary. As pages are 4096 bytes
|
||||
// aligned, `aligned_src` must be on the same page as `src`. A similar argument can be made
|
||||
// for `src + len`
|
||||
copy_quadwords(aligned_src as _, tmp_buff.as_mut_ptr(), aligned_len);
|
||||
|
||||
// Copy the correct parts of the temporary buffer to the destination
|
||||
ptr::copy(tmp_buff.as_ptr().add(pad0_size), dst, len);
|
||||
}
|
||||
}
|
||||
|
||||
assert!(!src.is_null());
|
||||
assert!(!dst.is_null());
|
||||
assert!(is_user_range(src, len));
|
||||
assert!(is_enclave_range(dst, len));
|
||||
assert!(!(src as usize).overflowing_add(len + 8).1);
|
||||
assert!(!(dst as usize).overflowing_add(len + 8).1);
|
||||
|
||||
if len < 8 {
|
||||
copy_misaligned_chunk_to_enclave(src, dst, len);
|
||||
} else if len % 8 == 0 && src as usize % 8 == 0 {
|
||||
// Copying 8-byte aligned quadwords: copy quad word per quad word
|
||||
unsafe {
|
||||
copy_quadwords(src, dst, len);
|
||||
}
|
||||
} else {
|
||||
// Split copies into three parts:
|
||||
// +--------+
|
||||
// | small0 | Chunk smaller than 8 bytes
|
||||
// +--------+
|
||||
// | big | Chunk 8-byte aligned, and size a multiple of 8 bytes
|
||||
// +--------+
|
||||
// | small1 | Chunk smaller than 8 bytes
|
||||
// +--------+
|
||||
let (small0_size, big_size, small1_size) = region_as_aligned_chunks(dst, len);
|
||||
|
||||
unsafe {
|
||||
// Copy small0
|
||||
copy_misaligned_chunk_to_enclave(src, dst, small0_size);
|
||||
|
||||
// Copy big
|
||||
let big_src = src.add(small0_size);
|
||||
let big_dst = dst.add(small0_size);
|
||||
copy_quadwords(big_src, big_dst, big_size);
|
||||
|
||||
// Copy small1
|
||||
let small1_src = src.add(big_size + small0_size);
|
||||
let small1_dst = dst.add(big_size + small0_size);
|
||||
copy_misaligned_chunk_to_enclave(small1_src, small1_dst, small1_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "sgx_platform", issue = "56975")]
|
||||
impl<T: ?Sized> UserRef<T>
|
||||
where
|
||||
@ -468,7 +581,7 @@ where
|
||||
pub fn copy_to_enclave(&self, dest: &mut T) {
|
||||
unsafe {
|
||||
assert_eq!(mem::size_of_val(dest), mem::size_of_val(&*self.0.get()));
|
||||
ptr::copy(
|
||||
copy_from_userspace(
|
||||
self.0.get() as *const T as *const u8,
|
||||
dest as *mut T as *mut u8,
|
||||
mem::size_of_val(dest),
|
||||
@ -494,7 +607,11 @@ where
|
||||
{
|
||||
/// Copies the value from user memory into enclave memory.
|
||||
pub fn to_enclave(&self) -> T {
|
||||
unsafe { ptr::read(self.0.get()) }
|
||||
unsafe {
|
||||
let mut data: T = mem::MaybeUninit::uninit().assume_init();
|
||||
copy_from_userspace(self.0.get() as _, &mut data as *mut T as _, mem::size_of::<T>());
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use super::alloc::copy_to_userspace;
|
||||
use super::alloc::User;
|
||||
use super::alloc::{copy_from_userspace, copy_to_userspace};
|
||||
|
||||
#[test]
|
||||
fn test_copy_function() {
|
||||
fn test_copy_to_userspace_function() {
|
||||
let mut src = [0u8; 100];
|
||||
let mut dst = User::<[u8]>::uninitialized(100);
|
||||
|
||||
@ -28,3 +28,29 @@ fn test_copy_function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_copy_from_userspace_function() {
|
||||
let mut dst = [0u8; 100];
|
||||
let mut src = User::<[u8]>::uninitialized(100);
|
||||
|
||||
src.copy_from_enclave(&[0u8; 100]);
|
||||
|
||||
for size in 0..48 {
|
||||
// For all possible alignment
|
||||
for offset in 0..8 {
|
||||
// overwrite complete dst
|
||||
dst = [0u8; 100];
|
||||
|
||||
// Copy src[0..size] to dst + offset
|
||||
unsafe { copy_from_userspace(src.as_ptr().offset(offset), dst.as_mut_ptr(), size) };
|
||||
|
||||
// Verify copy
|
||||
for byte in 0..size {
|
||||
unsafe {
|
||||
assert_eq!(dst[byte as usize], *src.as_ptr().offset(offset + byte as isize));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::io::ErrorKind;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||
use crate::path::PathBuf;
|
||||
use crate::time::Duration;
|
||||
@ -204,8 +205,8 @@ where
|
||||
// This initial size also works around `GetFullPathNameW` returning
|
||||
// incorrect size hints for some short paths:
|
||||
// https://github.com/dylni/normpath/issues/5
|
||||
let mut stack_buf = [0u16; 512];
|
||||
let mut heap_buf = Vec::new();
|
||||
let mut stack_buf: [MaybeUninit<u16>; 512] = MaybeUninit::uninit_array();
|
||||
let mut heap_buf: Vec<MaybeUninit<u16>> = Vec::new();
|
||||
unsafe {
|
||||
let mut n = stack_buf.len();
|
||||
loop {
|
||||
@ -214,6 +215,11 @@ where
|
||||
} else {
|
||||
let extra = n - heap_buf.len();
|
||||
heap_buf.reserve(extra);
|
||||
// We used `reserve` and not `reserve_exact`, so in theory we
|
||||
// may have gotten more than requested. If so, we'd like to use
|
||||
// it... so long as we won't cause overflow.
|
||||
n = heap_buf.capacity().min(c::DWORD::MAX as usize);
|
||||
// Safety: MaybeUninit<u16> does not need initialization
|
||||
heap_buf.set_len(n);
|
||||
&mut heap_buf[..]
|
||||
};
|
||||
@ -228,13 +234,13 @@ where
|
||||
// error" is still 0 then we interpret it as a 0 length buffer and
|
||||
// not an actual error.
|
||||
c::SetLastError(0);
|
||||
let k = match f1(buf.as_mut_ptr(), n as c::DWORD) {
|
||||
let k = match f1(buf.as_mut_ptr().cast::<u16>(), n as c::DWORD) {
|
||||
0 if c::GetLastError() == 0 => 0,
|
||||
0 => return Err(crate::io::Error::last_os_error()),
|
||||
n => n,
|
||||
} as usize;
|
||||
if k == n && c::GetLastError() == c::ERROR_INSUFFICIENT_BUFFER {
|
||||
n *= 2;
|
||||
n = n.saturating_mul(2).min(c::DWORD::MAX as usize);
|
||||
} else if k > n {
|
||||
n = k;
|
||||
} else if k == n {
|
||||
@ -244,7 +250,9 @@ where
|
||||
// Therefore k never equals n.
|
||||
unreachable!();
|
||||
} else {
|
||||
return Ok(f2(&buf[..k]));
|
||||
// Safety: First `k` values are initialized.
|
||||
let slice: &[u16] = MaybeUninit::slice_assume_init_ref(&buf[..k]);
|
||||
return Ok(f2(slice));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ LL | static settings_dir: String = format!("");
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0507]: cannot move out of static item `settings_dir`
|
||||
|
@ -5,6 +5,7 @@ LL | cb.map(|cb| cb());
|
||||
| ^^^--------------
|
||||
| | |
|
||||
| | `*cb` moved due to this method call
|
||||
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
|
||||
| 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`
|
||||
@ -12,10 +13,6 @@ note: this function takes ownership of the receiver `self`, which moves `*cb`
|
||||
|
|
||||
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
|
||||
|
@ -22,6 +22,7 @@ LL | field2: SafeEnum::Variant4("str".to_string())
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
|
||||
error[E0010]: allocations are not allowed in statics
|
||||
--> $DIR/check-static-values-constraints.rs:94:5
|
||||
|
@ -13,6 +13,7 @@ LL | invalid();
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
|
||||
error[E0015]: cannot call non-const fn `invalid` in statics
|
||||
--> $DIR/issue-32829-2.rs:54:9
|
||||
@ -21,6 +22,7 @@ LL | invalid();
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -5,6 +5,7 @@ LL | static foo: Foo = bar();
|
||||
| ^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
9
src/test/ui/issues/issue-100605.rs
Normal file
9
src/test/ui/issues/issue-100605.rs
Normal file
@ -0,0 +1,9 @@
|
||||
fn takes_option(_arg: Option<&String>) {}
|
||||
|
||||
fn main() {
|
||||
takes_option(&None); //~ ERROR 4:18: 4:23: mismatched types [E0308]
|
||||
|
||||
let x = String::from("x");
|
||||
let res = Some(x);
|
||||
takes_option(&res); //~ ERROR 8:18: 8:22: mismatched types [E0308]
|
||||
}
|
46
src/test/ui/issues/issue-100605.stderr
Normal file
46
src/test/ui/issues/issue-100605.stderr
Normal file
@ -0,0 +1,46 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-100605.rs:4:18
|
||||
|
|
||||
LL | takes_option(&None);
|
||||
| ------------ ^^^^^ expected enum `Option`, found `&Option<_>`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected enum `Option<&String>`
|
||||
found reference `&Option<_>`
|
||||
note: function defined here
|
||||
--> $DIR/issue-100605.rs:1:4
|
||||
|
|
||||
LL | fn takes_option(_arg: Option<&String>) {}
|
||||
| ^^^^^^^^^^^^ ---------------------
|
||||
help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`
|
||||
|
|
||||
LL | takes_option(None.as_ref());
|
||||
| ~~~~~~~~~~~~~
|
||||
help: consider removing the borrow
|
||||
|
|
||||
LL - takes_option(&None);
|
||||
LL + takes_option(None);
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-100605.rs:8:18
|
||||
|
|
||||
LL | takes_option(&res);
|
||||
| ------------ ^^^^
|
||||
| | |
|
||||
| | expected enum `Option`, found `&Option<String>`
|
||||
| | help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `res.as_ref()`
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected enum `Option<&String>`
|
||||
found reference `&Option<String>`
|
||||
note: function defined here
|
||||
--> $DIR/issue-100605.rs:1:4
|
||||
|
|
||||
LL | fn takes_option(_arg: Option<&String>) {}
|
||||
| ^^^^^^^^^^^^ ---------------------
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -5,6 +5,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
|
||||
error[E0133]: use of extern static is unsafe and requires unsafe function or block
|
||||
--> $DIR/issue-16538.rs:14:30
|
||||
|
@ -21,6 +21,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -16,6 +16,7 @@ note: impl defined here, but it is not `const`
|
||||
LL | impl Deref for A {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
10
src/test/ui/parser/fn-defined-using-def.rs
Normal file
10
src/test/ui/parser/fn-defined-using-def.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// Check what happens when `def` is used to define a function, instead of `fn`
|
||||
// edition:2021
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
def foo() {}
|
||||
//~^ ERROR expected one of `!` or `::`, found `foo`
|
||||
//~^^ HELP write `fn` instead of `def` to declare a function
|
||||
|
||||
fn main() {}
|
10
src/test/ui/parser/fn-defined-using-def.stderr
Normal file
10
src/test/ui/parser/fn-defined-using-def.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: expected one of `!` or `::`, found `foo`
|
||||
--> $DIR/fn-defined-using-def.rs:6:5
|
||||
|
|
||||
LL | def foo() {}
|
||||
| --- ^^^ expected one of `!` or `::`
|
||||
| |
|
||||
| help: write `fn` instead of `def` to declare a function
|
||||
|
||||
error: aborting due to previous error
|
||||
|
10
src/test/ui/parser/fn-defined-using-fun.rs
Normal file
10
src/test/ui/parser/fn-defined-using-fun.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// Check what happens when `fun` is used to define a function, instead of `fn`
|
||||
// edition:2021
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
fun foo() {}
|
||||
//~^ ERROR expected one of `!` or `::`, found `foo`
|
||||
//~^^ HELP write `fn` instead of `fun` to declare a function
|
||||
|
||||
fn main() {}
|
10
src/test/ui/parser/fn-defined-using-fun.stderr
Normal file
10
src/test/ui/parser/fn-defined-using-fun.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: expected one of `!` or `::`, found `foo`
|
||||
--> $DIR/fn-defined-using-fun.rs:6:5
|
||||
|
|
||||
LL | fun foo() {}
|
||||
| --- ^^^ expected one of `!` or `::`
|
||||
| |
|
||||
| help: write `fn` instead of `fun` to declare a function
|
||||
|
||||
error: aborting due to previous error
|
||||
|
10
src/test/ui/parser/fn-defined-using-func.rs
Normal file
10
src/test/ui/parser/fn-defined-using-func.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// Check what happens when `func` is used to define a function, instead of `fn`
|
||||
// edition:2021
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
func foo() {}
|
||||
//~^ ERROR expected one of `!` or `::`, found `foo`
|
||||
//~^^ HELP write `fn` instead of `func` to declare a function
|
||||
|
||||
fn main() {}
|
10
src/test/ui/parser/fn-defined-using-func.stderr
Normal file
10
src/test/ui/parser/fn-defined-using-func.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: expected one of `!` or `::`, found `foo`
|
||||
--> $DIR/fn-defined-using-func.rs:6:6
|
||||
|
|
||||
LL | func foo() {}
|
||||
| ---- ^^^ expected one of `!` or `::`
|
||||
| |
|
||||
| help: write `fn` instead of `func` to declare a function
|
||||
|
||||
error: aborting due to previous error
|
||||
|
10
src/test/ui/parser/fn-defined-using-function.rs
Normal file
10
src/test/ui/parser/fn-defined-using-function.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// Check what happens when `function` is used to define a function, instead of `fn`
|
||||
// edition:2021
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
function foo() {}
|
||||
//~^ ERROR expected one of `!` or `::`, found `foo`
|
||||
//~^^ HELP write `fn` instead of `function` to declare a function
|
||||
|
||||
fn main() {}
|
10
src/test/ui/parser/fn-defined-using-function.stderr
Normal file
10
src/test/ui/parser/fn-defined-using-function.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: expected one of `!` or `::`, found `foo`
|
||||
--> $DIR/fn-defined-using-function.rs:6:10
|
||||
|
|
||||
LL | function foo() {}
|
||||
| -------- ^^^ expected one of `!` or `::`
|
||||
| |
|
||||
| help: write `fn` instead of `function` to declare a function
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -5,6 +5,7 @@ LL | static a: [isize; 2] = [foo(); 2];
|
||||
| ^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
// run-rustfix
|
||||
|
||||
struct Struct;
|
||||
|
||||
fn bar(_: &Struct) -> Struct {
|
||||
Struct
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo = Some(Struct);
|
||||
let _x: Option<Struct> = foo.as_ref().map(|s| bar(&s));
|
||||
let _y = foo; //~ERROR use of moved value: `foo`
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
// run-rustfix
|
||||
|
||||
struct Struct;
|
||||
|
||||
fn bar(_: &Struct) -> Struct {
|
||||
|
@ -1,10 +1,12 @@
|
||||
error[E0382]: use of moved value: `foo`
|
||||
--> $DIR/as-ref-2.rs:12:14
|
||||
--> $DIR/as-ref-2.rs:10:14
|
||||
|
|
||||
LL | let foo = Some(Struct);
|
||||
| --- move occurs because `foo` has type `Option<Struct>`, which does not implement the `Copy` trait
|
||||
LL | let _x: Option<Struct> = foo.map(|s| bar(&s));
|
||||
| ---------------- `foo` moved due to this method call
|
||||
| --- ---------------- `foo` moved due to this method call
|
||||
| |
|
||||
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
|
||||
LL | let _y = foo;
|
||||
| ^^^ value used here after move
|
||||
|
|
||||
@ -13,10 +15,6 @@ note: this function takes ownership of the receiver `self`, which moves `foo`
|
||||
|
|
||||
LL | pub const fn map<U, F>(self, f: F) -> Option<U>
|
||||
| ^^^^
|
||||
help: consider calling `.as_ref()` to borrow the type's contents
|
||||
|
|
||||
LL | let _x: Option<Struct> = foo.as_ref().map(|s| bar(&s));
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,39 +0,0 @@
|
||||
//run-rustfix
|
||||
|
||||
pub struct LipogramCorpora {
|
||||
selections: Vec<(char, Option<String>)>,
|
||||
}
|
||||
|
||||
impl LipogramCorpora {
|
||||
pub fn validate_all(&mut self) -> Result<(), char> {
|
||||
for selection in &self.selections {
|
||||
if selection.1.is_some() {
|
||||
if selection.1.as_ref().unwrap().contains(selection.0) {
|
||||
//~^ ERROR cannot move out of `selection.1`
|
||||
return Err(selection.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LipogramCorpora2 {
|
||||
selections: Vec<(char, Result<String, String>)>,
|
||||
}
|
||||
|
||||
impl LipogramCorpora2 {
|
||||
pub fn validate_all(&mut self) -> Result<(), char> {
|
||||
for selection in &self.selections {
|
||||
if selection.1.is_ok() {
|
||||
if selection.1.as_ref().unwrap().contains(selection.0) {
|
||||
//~^ ERROR cannot move out of `selection.1`
|
||||
return Err(selection.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,5 +1,3 @@
|
||||
//run-rustfix
|
||||
|
||||
pub struct LipogramCorpora {
|
||||
selections: Vec<(char, Option<String>)>,
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
|
||||
--> $DIR/option-content-move.rs:11:20
|
||||
--> $DIR/option-content-move.rs:9:20
|
||||
|
|
||||
LL | if selection.1.unwrap().contains(selection.0) {
|
||||
| ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
|
||||
| |
|
||||
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
|
||||
| move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
|
||||
|
|
||||
note: this function takes ownership of the receiver `self`, which moves `selection.1`
|
||||
@ -11,17 +12,14 @@ note: this function takes ownership of the receiver `self`, which moves `selecti
|
||||
|
|
||||
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
|
||||
--> $DIR/option-content-move.rs:27:20
|
||||
|
|
||||
LL | if selection.1.unwrap().contains(selection.0) {
|
||||
| ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
|
||||
| |
|
||||
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
|
||||
| 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`
|
||||
@ -29,10 +27,6 @@ note: this function takes ownership of the receiver `self`, which moves `selecti
|
||||
|
|
||||
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
|
||||
|
||||
|
@ -129,6 +129,7 @@ trigger_files = [
|
||||
|
||||
# Internal tooling
|
||||
"src/etc/htmldocck.py",
|
||||
"src/etc/check_missing_items.py",
|
||||
"src/tools/jsondocck",
|
||||
"src/tools/rustdoc-gui",
|
||||
"src/tools/rustdoc-js",
|
||||
@ -138,6 +139,15 @@ exclude_labels = [
|
||||
"T-*",
|
||||
]
|
||||
|
||||
[autolabel."A-rustdoc-json"]
|
||||
trigger_files = [
|
||||
"src/etc/check_missing_items.py",
|
||||
"src/librustdoc/json/",
|
||||
"src/rustdoc-json-types",
|
||||
"src/test/rustdoc-json",
|
||||
"src/tools/jsondocck",
|
||||
]
|
||||
|
||||
[autolabel."T-compiler"]
|
||||
trigger_files = [
|
||||
# Source code
|
||||
|
Loading…
Reference in New Issue
Block a user