Auto merge of #114063 - matthiaskrgr:rollup-c90czu6, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #114008 (coverage: Obtain the `__llvm_covfun` section name outside a per-function loop) - #114014 (builtin_macros: expect raw strings too) - #114043 (docs(LazyLock): add example pass local LazyLock variable to struct) - #114051 (Add regression test for invalid "unused const" in method) - #114052 (Suggest `{Option,Result}::as_ref()` instead of `cloned()` in some cases) - #114058 (Add help for crate arg when crate name is invalid) - #114060 (abi: unsized field in union - assert to delay bug ) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
18fa7b9104
31 changed files with 319 additions and 74 deletions
|
@ -763,7 +763,9 @@ pub trait LayoutCalculator {
|
|||
let mut size = Size::ZERO;
|
||||
let only_variant = &variants[FIRST_VARIANT];
|
||||
for field in only_variant {
|
||||
assert!(field.0.is_sized());
|
||||
if field.0.is_unsized() {
|
||||
self.delay_bug("unsized field in union".to_string());
|
||||
}
|
||||
|
||||
align = align.max(field.align());
|
||||
max_repr_align = max_repr_align.max(field.max_repr_align());
|
||||
|
|
|
@ -1345,7 +1345,6 @@ impl Abi {
|
|||
|
||||
/// Discard validity range information and allow undef.
|
||||
pub fn to_union(&self) -> Self {
|
||||
assert!(self.is_sized());
|
||||
match *self {
|
||||
Abi::Scalar(s) => Abi::Scalar(s.to_union()),
|
||||
Abi::ScalarPair(s1, s2) => Abi::ScalarPair(s1.to_union(), s2.to_union()),
|
||||
|
|
|
@ -2306,11 +2306,10 @@ mod error {
|
|||
|
||||
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
|
||||
if let None = self.tainted_by_errors {
|
||||
self.tainted_by_errors = Some(
|
||||
self.tcx
|
||||
.sess
|
||||
.delay_span_bug(t.span.clone(), "diagnostic buffered but not emitted"),
|
||||
)
|
||||
self.tainted_by_errors = Some(self.tcx.sess.delay_span_bug(
|
||||
t.span.clone_ignoring_labels(),
|
||||
"diagnostic buffered but not emitted",
|
||||
))
|
||||
}
|
||||
t.buffer(&mut self.buffered);
|
||||
}
|
||||
|
|
|
@ -109,8 +109,8 @@ builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept
|
|||
.suggestion = remove the value
|
||||
|
||||
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
|
||||
.cargo = Cargo sets build script variables at run time. Use `std::env::var("{$var}")` instead
|
||||
.other = use `std::env::var("{$var}")` to read the variable at run time
|
||||
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
|
||||
.custom = use `std::env::var({$var_expr})` to read the variable at run time
|
||||
|
||||
builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//
|
||||
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{self as ast, GenericArg};
|
||||
use rustc_ast::{self as ast, AstDeref, GenericArg};
|
||||
use rustc_expand::base::{self, *};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
@ -76,27 +76,36 @@ pub fn expand_env<'cx>(
|
|||
},
|
||||
};
|
||||
|
||||
let sp = cx.with_def_site_ctxt(sp);
|
||||
let span = cx.with_def_site_ctxt(sp);
|
||||
let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
|
||||
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
|
||||
let e = match value {
|
||||
None => {
|
||||
// Use the string literal in the code in the diagnostic to avoid confusing diagnostics,
|
||||
// e.g. when the literal contains escape sequences.
|
||||
let ast::ExprKind::Lit(ast::token::Lit {
|
||||
kind: ast::token::LitKind::Str,
|
||||
symbol: original_var,
|
||||
kind: ast::token::LitKind::Str | ast::token::LitKind::StrRaw(..),
|
||||
symbol,
|
||||
..
|
||||
}) = &var_expr.kind
|
||||
else {
|
||||
unreachable!("`expr_to_string` ensures this is a string lit")
|
||||
};
|
||||
cx.emit_err(errors::EnvNotDefined {
|
||||
span: sp,
|
||||
msg: custom_msg,
|
||||
var: *original_var,
|
||||
help: custom_msg.is_none().then(|| help_for_missing_env_var(var.as_str())),
|
||||
});
|
||||
|
||||
if let Some(msg_from_user) = custom_msg {
|
||||
cx.emit_err(errors::EnvNotDefinedWithUserMessage { span, msg_from_user });
|
||||
} else if is_cargo_env_var(var.as_str()) {
|
||||
cx.emit_err(errors::EnvNotDefined::CargoEnvVar {
|
||||
span,
|
||||
var: *symbol,
|
||||
var_expr: var_expr.ast_deref(),
|
||||
});
|
||||
} else {
|
||||
cx.emit_err(errors::EnvNotDefined::CustomEnvVar {
|
||||
span,
|
||||
var: *symbol,
|
||||
var_expr: var_expr.ast_deref(),
|
||||
});
|
||||
}
|
||||
|
||||
return DummyResult::any(sp);
|
||||
}
|
||||
Some(value) => cx.expr_str(sp, value),
|
||||
|
@ -104,13 +113,9 @@ pub fn expand_env<'cx>(
|
|||
MacEager::expr(e)
|
||||
}
|
||||
|
||||
fn help_for_missing_env_var(var: &str) -> errors::EnvNotDefinedHelp {
|
||||
if var.starts_with("CARGO_")
|
||||
/// Returns `true` if an environment variable from `env!` is one used by Cargo.
|
||||
fn is_cargo_env_var(var: &str) -> bool {
|
||||
var.starts_with("CARGO_")
|
||||
|| var.starts_with("DEP_")
|
||||
|| matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET")
|
||||
{
|
||||
errors::EnvNotDefinedHelp::CargoVar
|
||||
} else {
|
||||
errors::EnvNotDefinedHelp::Other
|
||||
}
|
||||
}
|
||||
|
|
|
@ -440,43 +440,43 @@ pub(crate) struct EnvTakesArgs {
|
|||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
//#[derive(Diagnostic)]
|
||||
//#[diag(builtin_macros_env_not_defined)]
|
||||
pub(crate) struct EnvNotDefined {
|
||||
pub(crate) struct EnvNotDefinedWithUserMessage {
|
||||
pub(crate) span: Span,
|
||||
pub(crate) msg: Option<Symbol>,
|
||||
pub(crate) var: Symbol,
|
||||
pub(crate) help: Option<EnvNotDefinedHelp>,
|
||||
pub(crate) msg_from_user: Symbol,
|
||||
}
|
||||
|
||||
// Hand-written implementation to support custom user messages
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefined {
|
||||
// Hand-written implementation to support custom user messages.
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMessage {
|
||||
#[track_caller]
|
||||
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, G> {
|
||||
let mut diag = if let Some(msg) = self.msg {
|
||||
#[expect(
|
||||
rustc::untranslatable_diagnostic,
|
||||
reason = "cannot translate user-provided messages"
|
||||
)]
|
||||
handler.struct_diagnostic(msg.to_string())
|
||||
} else {
|
||||
handler.struct_diagnostic(crate::fluent_generated::builtin_macros_env_not_defined)
|
||||
};
|
||||
diag.set_arg("var", self.var);
|
||||
#[expect(
|
||||
rustc::untranslatable_diagnostic,
|
||||
reason = "cannot translate user-provided messages"
|
||||
)]
|
||||
let mut diag = handler.struct_diagnostic(self.msg_from_user.to_string());
|
||||
diag.set_span(self.span);
|
||||
if let Some(help) = self.help {
|
||||
diag.subdiagnostic(help);
|
||||
}
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum EnvNotDefinedHelp {
|
||||
#[derive(Diagnostic)]
|
||||
pub(crate) enum EnvNotDefined<'a> {
|
||||
#[diag(builtin_macros_env_not_defined)]
|
||||
#[help(builtin_macros_cargo)]
|
||||
CargoVar,
|
||||
#[help(builtin_macros_other)]
|
||||
Other,
|
||||
CargoEnvVar {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
var: Symbol,
|
||||
var_expr: &'a rustc_ast::Expr,
|
||||
},
|
||||
#[diag(builtin_macros_env_not_defined)]
|
||||
#[help(builtin_macros_custom)]
|
||||
CustomEnvVar {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
var: Symbol,
|
||||
var_expr: &'a rustc_ast::Expr,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
@ -100,9 +100,11 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
|
|||
// Generate the LLVM IR representation of the coverage map and store it in a well-known global
|
||||
let cov_data_val = mapgen.generate_coverage_map(cx, version, filenames_size, filenames_val);
|
||||
|
||||
let covfun_section_name = coverageinfo::covfun_section_name(cx);
|
||||
for (mangled_function_name, source_hash, is_used, coverage_mapping_buffer) in function_data {
|
||||
save_function_record(
|
||||
cx,
|
||||
&covfun_section_name,
|
||||
mangled_function_name,
|
||||
source_hash,
|
||||
filenames_ref,
|
||||
|
@ -228,6 +230,7 @@ impl CoverageMapGenerator {
|
|||
/// specific, well-known section and name.
|
||||
fn save_function_record(
|
||||
cx: &CodegenCx<'_, '_>,
|
||||
covfun_section_name: &str,
|
||||
mangled_function_name: &str,
|
||||
source_hash: u64,
|
||||
filenames_ref: u64,
|
||||
|
@ -254,7 +257,13 @@ fn save_function_record(
|
|||
/*packed=*/ true,
|
||||
);
|
||||
|
||||
coverageinfo::save_func_record_to_mod(cx, func_name_hash, func_record_val, is_used);
|
||||
coverageinfo::save_func_record_to_mod(
|
||||
cx,
|
||||
covfun_section_name,
|
||||
func_name_hash,
|
||||
func_record_val,
|
||||
is_used,
|
||||
);
|
||||
}
|
||||
|
||||
/// When finalizing the coverage map, `FunctionCoverage` only has the `CodeRegion`s and counters for
|
||||
|
|
|
@ -408,6 +408,7 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>(
|
|||
|
||||
pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
covfun_section_name: &str,
|
||||
func_name_hash: u64,
|
||||
func_record_val: &'ll llvm::Value,
|
||||
is_used: bool,
|
||||
|
@ -423,20 +424,33 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
|
|||
let func_record_var_name =
|
||||
format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" });
|
||||
debug!("function record var name: {:?}", func_record_var_name);
|
||||
|
||||
let func_record_section_name = llvm::build_string(|s| unsafe {
|
||||
llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s);
|
||||
})
|
||||
.expect("Rust Coverage function record section name failed UTF-8 conversion");
|
||||
debug!("function record section name: {:?}", func_record_section_name);
|
||||
debug!("function record section name: {:?}", covfun_section_name);
|
||||
|
||||
let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name);
|
||||
llvm::set_initializer(llglobal, func_record_val);
|
||||
llvm::set_global_constant(llglobal, true);
|
||||
llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
|
||||
llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
|
||||
llvm::set_section(llglobal, &func_record_section_name);
|
||||
llvm::set_section(llglobal, covfun_section_name);
|
||||
llvm::set_alignment(llglobal, VAR_ALIGN_BYTES);
|
||||
llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
|
||||
cx.add_used_global(llglobal);
|
||||
}
|
||||
|
||||
/// Returns the section name string to pass through to the linker when embedding
|
||||
/// per-function coverage information in the object file, according to the target
|
||||
/// platform's object file format.
|
||||
///
|
||||
/// LLVM's coverage tools read coverage mapping details from this section when
|
||||
/// producing coverage reports.
|
||||
///
|
||||
/// Typical values are:
|
||||
/// - `__llvm_covfun` on Linux
|
||||
/// - `__LLVM_COV,__llvm_covfun` on macOS (includes `__LLVM_COV,` segment prefix)
|
||||
/// - `.lcovfun$M` on Windows (includes `$M` sorting suffix)
|
||||
pub(crate) fn covfun_section_name(cx: &CodegenCx<'_, '_>) -> String {
|
||||
llvm::build_string(|s| unsafe {
|
||||
llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s);
|
||||
})
|
||||
.expect("Rust Coverage function record section name failed UTF-8 conversion")
|
||||
}
|
||||
|
|
|
@ -533,6 +533,14 @@ impl MultiSpan {
|
|||
pub fn has_span_labels(&self) -> bool {
|
||||
self.span_labels.iter().any(|(sp, _)| !sp.is_dummy())
|
||||
}
|
||||
|
||||
/// Clone this `MultiSpan` without keeping any of the span labels - sometimes a `MultiSpan` is
|
||||
/// to be re-used in another diagnostic, but includes `span_labels` which have translated
|
||||
/// messages. These translated messages would fail to translate without their diagnostic
|
||||
/// arguments which are unlikely to be cloned alongside the `Span`.
|
||||
pub fn clone_ignoring_labels(&self) -> Self {
|
||||
Self { primary_spans: self.primary_spans.clone(), ..MultiSpan::new() }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Span> for MultiSpan {
|
||||
|
|
|
@ -164,6 +164,12 @@ impl IntoDiagnosticArg for hir::ConstContext {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for ast::Expr {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(pprust::expr_to_string(&self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for ast::Path {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(&self)))
|
||||
|
|
|
@ -53,7 +53,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|| self.suggest_no_capture_closure(err, expected, expr_ty)
|
||||
|| self.suggest_boxing_when_appropriate(err, expr.span, expr.hir_id, expected, expr_ty)
|
||||
|| self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
|
||||
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
|
||||
|| self.suggest_copied_cloned_or_as_ref(err, expr, expr_ty, expected, expected_ty_expr)
|
||||
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
|
||||
|| self.suggest_into(err, expr, expr_ty, expected)
|
||||
|| self.suggest_floating_point_literal(err, expr, expected)
|
||||
|
|
|
@ -1085,12 +1085,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
false
|
||||
}
|
||||
|
||||
pub(crate) fn suggest_copied_or_cloned(
|
||||
pub(crate) fn suggest_copied_cloned_or_as_ref(
|
||||
&self,
|
||||
diag: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
expr_ty: Ty<'tcx>,
|
||||
expected_ty: Ty<'tcx>,
|
||||
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
) -> bool {
|
||||
let ty::Adt(adt_def, args) = expr_ty.kind() else {
|
||||
return false;
|
||||
|
@ -1102,7 +1103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return false;
|
||||
}
|
||||
|
||||
let mut suggest_copied_or_cloned = || {
|
||||
let mut suggest_copied_cloned_or_as_ref = || {
|
||||
let expr_inner_ty = args.type_at(0);
|
||||
let expected_inner_ty = expected_args.type_at(0);
|
||||
if let &ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
|
||||
|
@ -1119,6 +1120,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Applicability::MachineApplicable,
|
||||
);
|
||||
return true;
|
||||
} else if let Some(expected_ty_expr) = expected_ty_expr {
|
||||
diag.span_suggestion_verbose(
|
||||
expected_ty_expr.span.shrink_to_hi(),
|
||||
format!(
|
||||
"use `{def_path}::as_ref()` to convert `{expected_ty}` to `{expr_ty}`"
|
||||
),
|
||||
".as_ref()",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
return true;
|
||||
} else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
|
||||
&& rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
|
||||
self,
|
||||
|
@ -1146,11 +1157,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Check that the error types are equal
|
||||
&& self.can_eq(self.param_env, args.type_at(1), expected_args.type_at(1))
|
||||
{
|
||||
return suggest_copied_or_cloned();
|
||||
return suggest_copied_cloned_or_as_ref();
|
||||
} else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option)
|
||||
&& adt_def.did() == option_did
|
||||
{
|
||||
return suggest_copied_or_cloned();
|
||||
return suggest_copied_cloned_or_as_ref();
|
||||
}
|
||||
|
||||
false
|
||||
|
|
|
@ -45,6 +45,7 @@ session_int_literal_too_large = integer literal is too large
|
|||
.note = value exceeds limit of `{$limit}`
|
||||
|
||||
session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}`
|
||||
session_invalid_character_in_create_name_help = you can either pass `--crate-name` on the command line or add `#![crate_name="…"]` to set the crate name
|
||||
|
||||
session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
|
||||
.label = invalid suffix `{$suffix}`
|
||||
|
|
|
@ -199,6 +199,14 @@ pub struct InvalidCharacterInCrateName {
|
|||
pub span: Option<Span>,
|
||||
pub character: char,
|
||||
pub crate_name: Symbol,
|
||||
#[subdiagnostic]
|
||||
pub crate_name_help: Option<InvalidCrateNameHelp>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum InvalidCrateNameHelp {
|
||||
#[help(session_invalid_character_in_create_name_help)]
|
||||
AddCrateName,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use crate::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
|
||||
use crate::errors::{
|
||||
CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable,
|
||||
InvalidCharacterInCrateName,
|
||||
InvalidCharacterInCrateName, InvalidCrateNameHelp,
|
||||
};
|
||||
use crate::Session;
|
||||
use rustc_ast::{self as ast, attr};
|
||||
|
@ -101,7 +101,16 @@ pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) {
|
|||
continue;
|
||||
}
|
||||
err_count += 1;
|
||||
sess.emit_err(InvalidCharacterInCrateName { span: sp, character: c, crate_name: s });
|
||||
sess.emit_err(InvalidCharacterInCrateName {
|
||||
span: sp,
|
||||
character: c,
|
||||
crate_name: s,
|
||||
crate_name_help: if sp.is_none() {
|
||||
Some(InvalidCrateNameHelp::AddCrateName)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ union Data<T, F> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Initialize static variables with `LazyLock`.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(lazy_cell)]
|
||||
///
|
||||
|
@ -54,6 +56,24 @@ union Data<T, F> {
|
|||
/// // Some("Hoyten")
|
||||
/// }
|
||||
/// ```
|
||||
/// Initialize fields with `LazyLock`.
|
||||
/// ```
|
||||
/// #![feature(lazy_cell)]
|
||||
///
|
||||
/// use std::sync::LazyLock;
|
||||
///
|
||||
/// #[derive(Debug)]
|
||||
/// struct UseCellLock {
|
||||
/// number: LazyLock<u32>,
|
||||
/// }
|
||||
/// fn main() {
|
||||
/// let lock: LazyLock<u32> = LazyLock::new(|| 0u32);
|
||||
///
|
||||
/// let data = UseCellLock { number: lock };
|
||||
/// println!("{}", *data.number);
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
pub struct LazyLock<T, F = fn() -> T> {
|
||||
once: Once,
|
||||
|
|
|
@ -328,7 +328,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
|
|||
{
|
||||
// Don't lint. Byte strings produce `&[u8; N]` whereas `as_bytes()` produces
|
||||
// `&[u8]`. This change would prevent matching with different sized slices.
|
||||
} else {
|
||||
} else if !callsite.starts_with("env!") {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
STRING_LIT_AS_BYTES,
|
||||
|
|
|
@ -116,7 +116,9 @@ pub fn check(path: &Path, bad: &mut bool) {
|
|||
// must strip all of them.
|
||||
let testname =
|
||||
file_path.file_name().unwrap().to_str().unwrap().split_once('.').unwrap().0;
|
||||
if !file_path.with_file_name(testname).with_extension("rs").exists() {
|
||||
if !file_path.with_file_name(testname).with_extension("rs").exists()
|
||||
&& !testname.contains("ignore-tidy")
|
||||
{
|
||||
tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// run-rustfix
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub fn foo<I: Iterator>(mut iter: I, value: &I::Item)
|
||||
where
|
||||
I::Item: Eq + Debug,
|
||||
{
|
||||
debug_assert_eq!(iter.next().as_ref(), Some(value));
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -1,6 +1,8 @@
|
|||
// run-rustfix
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
fn foo<I: Iterator>(mut iter: I, value: &I::Item)
|
||||
pub fn foo<I: Iterator>(mut iter: I, value: &I::Item)
|
||||
where
|
||||
I::Item: Eq + Debug,
|
||||
{
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-suggest-cyclic-constraint.rs:7:35
|
||||
--> $DIR/dont-suggest-cyclic-constraint.rs:9:35
|
||||
|
|
||||
LL | debug_assert_eq!(iter.next(), Some(value));
|
||||
| ^^^^^^^^^^^ expected `Option<<I as Iterator>::Item>`, found `Option<&<I as Iterator>::Item>`
|
||||
|
|
||||
= note: expected enum `Option<<I as Iterator>::Item>`
|
||||
found enum `Option<&<I as Iterator>::Item>`
|
||||
help: use `Option::as_ref()` to convert `Option<<I as Iterator>::Item>` to `Option<&<I as Iterator>::Item>`
|
||||
|
|
||||
LL | debug_assert_eq!(iter.next().as_ref(), Some(value));
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
2
tests/ui/command/need-crate-arg-ignore-tidy.x.rs
Normal file
2
tests/ui/command/need-crate-arg-ignore-tidy.x.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
// issue: 113981
|
||||
pub fn main() {}
|
6
tests/ui/command/need-crate-arg-ignore-tidy.x.stderr
Normal file
6
tests/ui/command/need-crate-arg-ignore-tidy.x.stderr
Normal file
|
@ -0,0 +1,6 @@
|
|||
error: invalid character `'.'` in crate name: `need_crate_arg_ignore_tidy.x`
|
||||
|
|
||||
= help: you can either pass `--crate-name` on the command line or add `#![crate_name="…"]` to set the crate name
|
||||
|
||||
error: aborting due to previous error
|
||||
|
27
tests/ui/generator/issue-113279.rs
Normal file
27
tests/ui/generator/issue-113279.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
#![feature(generators)]
|
||||
|
||||
// `foo` attempts to dereference `""`, which results in an error being reported. Later, the
|
||||
// generator transform for `foo` then produces a union which contains a `str` type - unions should
|
||||
// not contain unsized types, but this is okay because an error has been reported already.
|
||||
// When const propagation happens later in compilation, it attempts to compute the layout of the
|
||||
// generator (as part of checking whether something can be const propagated) and in turn attempts
|
||||
// to compute the layout of `str` in the context of a union - where this caused an ICE. This test
|
||||
// makes sure that doesn't happen again.
|
||||
|
||||
fn foo() {
|
||||
let _y = static || {
|
||||
let x = &mut 0;
|
||||
*{
|
||||
yield;
|
||||
x
|
||||
} += match { *"" }.len() {
|
||||
//~^ ERROR cannot move a value of type `str` [E0161]
|
||||
//~^^ ERROR cannot move out of a shared reference [E0507]
|
||||
_ => 0,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo()
|
||||
}
|
16
tests/ui/generator/issue-113279.stderr
Normal file
16
tests/ui/generator/issue-113279.stderr
Normal file
|
@ -0,0 +1,16 @@
|
|||
error[E0161]: cannot move a value of type `str`
|
||||
--> $DIR/issue-113279.rs:17:20
|
||||
|
|
||||
LL | } += match { *"" }.len() {
|
||||
| ^^^^^^^ the size of `str` cannot be statically determined
|
||||
|
||||
error[E0507]: cannot move out of a shared reference
|
||||
--> $DIR/issue-113279.rs:17:22
|
||||
|
|
||||
LL | } += match { *"" }.len() {
|
||||
| ^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0161, E0507.
|
||||
For more information about an error, try `rustc --explain E0161`.
|
23
tests/ui/lint/unused/const-local-var.rs
Normal file
23
tests/ui/lint/unused/const-local-var.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// regression test for https://github.com/rust-lang/rust/issues/69016
|
||||
// check-pass
|
||||
|
||||
#![warn(unused)]
|
||||
#![deny(warnings)]
|
||||
|
||||
fn _unused1(x: i32) -> i32 {
|
||||
const F: i32 = 2;
|
||||
let g = 1;
|
||||
x * F + g
|
||||
}
|
||||
|
||||
pub struct Foo {}
|
||||
|
||||
impl Foo {
|
||||
fn _unused2(x: i32) -> i32 {
|
||||
const F: i32 = 2;
|
||||
let g = 1;
|
||||
x * F + g
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
10
tests/ui/macros/builtin-env-issue-114010.rs
Normal file
10
tests/ui/macros/builtin-env-issue-114010.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
// unset-rustc-env:oopsie
|
||||
// unset-rustc-env:a""a
|
||||
|
||||
env![r#"oopsie"#];
|
||||
//~^ ERROR environment variable `oopsie` not defined at compile time
|
||||
|
||||
env![r#"a""a"#];
|
||||
//~^ ERROR environment variable `a""a` not defined at compile time
|
||||
|
||||
fn main() {}
|
20
tests/ui/macros/builtin-env-issue-114010.stderr
Normal file
20
tests/ui/macros/builtin-env-issue-114010.stderr
Normal file
|
@ -0,0 +1,20 @@
|
|||
error: environment variable `oopsie` not defined at compile time
|
||||
--> $DIR/builtin-env-issue-114010.rs:4:1
|
||||
|
|
||||
LL | env![r#"oopsie"#];
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: use `std::env::var(r#"oopsie"#)` to read the variable at run time
|
||||
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: environment variable `a""a` not defined at compile time
|
||||
--> $DIR/builtin-env-issue-114010.rs:7:1
|
||||
|
|
||||
LL | env![r#"a""a"#];
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: use `std::env::var(r#"a""a"#)` to read the variable at run time
|
||||
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
@ -20,4 +20,12 @@ fn main() {
|
|||
expect::<Result<String, ()>>(x.cloned());
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP use `Result::cloned` to clone the value inside the `Result`
|
||||
|
||||
let s = String::new();
|
||||
let x = Some(s.clone());
|
||||
let y = Some(&s);
|
||||
println!("{}", x.as_ref() == y);
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP use `Option::as_ref()` to convert `Option<String>` to `Option<&String>`
|
||||
|
||||
}
|
||||
|
|
|
@ -20,4 +20,12 @@ fn main() {
|
|||
expect::<Result<String, ()>>(x);
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP use `Result::cloned` to clone the value inside the `Result`
|
||||
|
||||
let s = String::new();
|
||||
let x = Some(s.clone());
|
||||
let y = Some(&s);
|
||||
println!("{}", x == y);
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP use `Option::as_ref()` to convert `Option<String>` to `Option<&String>`
|
||||
|
||||
}
|
||||
|
|
|
@ -78,6 +78,19 @@ help: use `Result::cloned` to clone the value inside the `Result`
|
|||
LL | expect::<Result<String, ()>>(x.cloned());
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/copied-and-cloned.rs:27:25
|
||||
|
|
||||
LL | println!("{}", x == y);
|
||||
| ^ expected `Option<String>`, found `Option<&String>`
|
||||
|
|
||||
= note: expected enum `Option<String>`
|
||||
found enum `Option<&String>`
|
||||
help: use `Option::as_ref()` to convert `Option<String>` to `Option<&String>`
|
||||
|
|
||||
LL | println!("{}", x.as_ref() == y);
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue