Skip to content

Commit 18fa7b9

Browse files
committed
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
2 parents 8327047 + ba6982b commit 18fa7b9

File tree

31 files changed

+319
-74
lines changed

31 files changed

+319
-74
lines changed

compiler/rustc_abi/src/layout.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,9 @@ pub trait LayoutCalculator {
763763
let mut size = Size::ZERO;
764764
let only_variant = &variants[FIRST_VARIANT];
765765
for field in only_variant {
766-
assert!(field.0.is_sized());
766+
if field.0.is_unsized() {
767+
self.delay_bug("unsized field in union".to_string());
768+
}
767769

768770
align = align.max(field.align());
769771
max_repr_align = max_repr_align.max(field.max_repr_align());

compiler/rustc_abi/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1345,7 +1345,6 @@ impl Abi {
13451345

13461346
/// Discard validity range information and allow undef.
13471347
pub fn to_union(&self) -> Self {
1348-
assert!(self.is_sized());
13491348
match *self {
13501349
Abi::Scalar(s) => Abi::Scalar(s.to_union()),
13511350
Abi::ScalarPair(s1, s2) => Abi::ScalarPair(s1.to_union(), s2.to_union()),

compiler/rustc_borrowck/src/lib.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -2306,11 +2306,10 @@ mod error {
23062306

23072307
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
23082308
if let None = self.tainted_by_errors {
2309-
self.tainted_by_errors = Some(
2310-
self.tcx
2311-
.sess
2312-
.delay_span_bug(t.span.clone(), "diagnostic buffered but not emitted"),
2313-
)
2309+
self.tainted_by_errors = Some(self.tcx.sess.delay_span_bug(
2310+
t.span.clone_ignoring_labels(),
2311+
"diagnostic buffered but not emitted",
2312+
))
23142313
}
23152314
t.buffer(&mut self.buffered);
23162315
}

compiler/rustc_builtin_macros/messages.ftl

+2-2
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept
109109
.suggestion = remove the value
110110
111111
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
112-
.cargo = Cargo sets build script variables at run time. Use `std::env::var("{$var}")` instead
113-
.other = use `std::env::var("{$var}")` to read the variable at run time
112+
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
113+
.custom = use `std::env::var({$var_expr})` to read the variable at run time
114114
115115
builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments
116116

compiler/rustc_builtin_macros/src/env.rs

+24-19
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//
55

66
use rustc_ast::tokenstream::TokenStream;
7-
use rustc_ast::{self as ast, GenericArg};
7+
use rustc_ast::{self as ast, AstDeref, GenericArg};
88
use rustc_expand::base::{self, *};
99
use rustc_span::symbol::{kw, sym, Ident, Symbol};
1010
use rustc_span::Span;
@@ -76,41 +76,46 @@ pub fn expand_env<'cx>(
7676
},
7777
};
7878

79-
let sp = cx.with_def_site_ctxt(sp);
79+
let span = cx.with_def_site_ctxt(sp);
8080
let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
8181
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
8282
let e = match value {
8383
None => {
84-
// Use the string literal in the code in the diagnostic to avoid confusing diagnostics,
85-
// e.g. when the literal contains escape sequences.
8684
let ast::ExprKind::Lit(ast::token::Lit {
87-
kind: ast::token::LitKind::Str,
88-
symbol: original_var,
85+
kind: ast::token::LitKind::Str | ast::token::LitKind::StrRaw(..),
86+
symbol,
8987
..
9088
}) = &var_expr.kind
9189
else {
9290
unreachable!("`expr_to_string` ensures this is a string lit")
9391
};
94-
cx.emit_err(errors::EnvNotDefined {
95-
span: sp,
96-
msg: custom_msg,
97-
var: *original_var,
98-
help: custom_msg.is_none().then(|| help_for_missing_env_var(var.as_str())),
99-
});
92+
93+
if let Some(msg_from_user) = custom_msg {
94+
cx.emit_err(errors::EnvNotDefinedWithUserMessage { span, msg_from_user });
95+
} else if is_cargo_env_var(var.as_str()) {
96+
cx.emit_err(errors::EnvNotDefined::CargoEnvVar {
97+
span,
98+
var: *symbol,
99+
var_expr: var_expr.ast_deref(),
100+
});
101+
} else {
102+
cx.emit_err(errors::EnvNotDefined::CustomEnvVar {
103+
span,
104+
var: *symbol,
105+
var_expr: var_expr.ast_deref(),
106+
});
107+
}
108+
100109
return DummyResult::any(sp);
101110
}
102111
Some(value) => cx.expr_str(sp, value),
103112
};
104113
MacEager::expr(e)
105114
}
106115

107-
fn help_for_missing_env_var(var: &str) -> errors::EnvNotDefinedHelp {
108-
if var.starts_with("CARGO_")
116+
/// Returns `true` if an environment variable from `env!` is one used by Cargo.
117+
fn is_cargo_env_var(var: &str) -> bool {
118+
var.starts_with("CARGO_")
109119
|| var.starts_with("DEP_")
110120
|| matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET")
111-
{
112-
errors::EnvNotDefinedHelp::CargoVar
113-
} else {
114-
errors::EnvNotDefinedHelp::Other
115-
}
116121
}

compiler/rustc_builtin_macros/src/errors.rs

+26-26
Original file line numberDiff line numberDiff line change
@@ -440,43 +440,43 @@ pub(crate) struct EnvTakesArgs {
440440
pub(crate) span: Span,
441441
}
442442

443-
//#[derive(Diagnostic)]
444-
//#[diag(builtin_macros_env_not_defined)]
445-
pub(crate) struct EnvNotDefined {
443+
pub(crate) struct EnvNotDefinedWithUserMessage {
446444
pub(crate) span: Span,
447-
pub(crate) msg: Option<Symbol>,
448-
pub(crate) var: Symbol,
449-
pub(crate) help: Option<EnvNotDefinedHelp>,
445+
pub(crate) msg_from_user: Symbol,
450446
}
451447

452-
// Hand-written implementation to support custom user messages
453-
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefined {
448+
// Hand-written implementation to support custom user messages.
449+
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMessage {
454450
#[track_caller]
455451
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, G> {
456-
let mut diag = if let Some(msg) = self.msg {
457-
#[expect(
458-
rustc::untranslatable_diagnostic,
459-
reason = "cannot translate user-provided messages"
460-
)]
461-
handler.struct_diagnostic(msg.to_string())
462-
} else {
463-
handler.struct_diagnostic(crate::fluent_generated::builtin_macros_env_not_defined)
464-
};
465-
diag.set_arg("var", self.var);
452+
#[expect(
453+
rustc::untranslatable_diagnostic,
454+
reason = "cannot translate user-provided messages"
455+
)]
456+
let mut diag = handler.struct_diagnostic(self.msg_from_user.to_string());
466457
diag.set_span(self.span);
467-
if let Some(help) = self.help {
468-
diag.subdiagnostic(help);
469-
}
470458
diag
471459
}
472460
}
473461

474-
#[derive(Subdiagnostic)]
475-
pub(crate) enum EnvNotDefinedHelp {
462+
#[derive(Diagnostic)]
463+
pub(crate) enum EnvNotDefined<'a> {
464+
#[diag(builtin_macros_env_not_defined)]
476465
#[help(builtin_macros_cargo)]
477-
CargoVar,
478-
#[help(builtin_macros_other)]
479-
Other,
466+
CargoEnvVar {
467+
#[primary_span]
468+
span: Span,
469+
var: Symbol,
470+
var_expr: &'a rustc_ast::Expr,
471+
},
472+
#[diag(builtin_macros_env_not_defined)]
473+
#[help(builtin_macros_custom)]
474+
CustomEnvVar {
475+
#[primary_span]
476+
span: Span,
477+
var: Symbol,
478+
var_expr: &'a rustc_ast::Expr,
479+
},
480480
}
481481

482482
#[derive(Diagnostic)]

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,11 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
100100
// Generate the LLVM IR representation of the coverage map and store it in a well-known global
101101
let cov_data_val = mapgen.generate_coverage_map(cx, version, filenames_size, filenames_val);
102102

103+
let covfun_section_name = coverageinfo::covfun_section_name(cx);
103104
for (mangled_function_name, source_hash, is_used, coverage_mapping_buffer) in function_data {
104105
save_function_record(
105106
cx,
107+
&covfun_section_name,
106108
mangled_function_name,
107109
source_hash,
108110
filenames_ref,
@@ -228,6 +230,7 @@ impl CoverageMapGenerator {
228230
/// specific, well-known section and name.
229231
fn save_function_record(
230232
cx: &CodegenCx<'_, '_>,
233+
covfun_section_name: &str,
231234
mangled_function_name: &str,
232235
source_hash: u64,
233236
filenames_ref: u64,
@@ -254,7 +257,13 @@ fn save_function_record(
254257
/*packed=*/ true,
255258
);
256259

257-
coverageinfo::save_func_record_to_mod(cx, func_name_hash, func_record_val, is_used);
260+
coverageinfo::save_func_record_to_mod(
261+
cx,
262+
covfun_section_name,
263+
func_name_hash,
264+
func_record_val,
265+
is_used,
266+
);
258267
}
259268

260269
/// When finalizing the coverage map, `FunctionCoverage` only has the `CodeRegion`s and counters for

compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>(
408408

409409
pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
410410
cx: &CodegenCx<'ll, 'tcx>,
411+
covfun_section_name: &str,
411412
func_name_hash: u64,
412413
func_record_val: &'ll llvm::Value,
413414
is_used: bool,
@@ -423,20 +424,33 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
423424
let func_record_var_name =
424425
format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" });
425426
debug!("function record var name: {:?}", func_record_var_name);
426-
427-
let func_record_section_name = llvm::build_string(|s| unsafe {
428-
llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s);
429-
})
430-
.expect("Rust Coverage function record section name failed UTF-8 conversion");
431-
debug!("function record section name: {:?}", func_record_section_name);
427+
debug!("function record section name: {:?}", covfun_section_name);
432428

433429
let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name);
434430
llvm::set_initializer(llglobal, func_record_val);
435431
llvm::set_global_constant(llglobal, true);
436432
llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
437433
llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
438-
llvm::set_section(llglobal, &func_record_section_name);
434+
llvm::set_section(llglobal, covfun_section_name);
439435
llvm::set_alignment(llglobal, VAR_ALIGN_BYTES);
440436
llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
441437
cx.add_used_global(llglobal);
442438
}
439+
440+
/// Returns the section name string to pass through to the linker when embedding
441+
/// per-function coverage information in the object file, according to the target
442+
/// platform's object file format.
443+
///
444+
/// LLVM's coverage tools read coverage mapping details from this section when
445+
/// producing coverage reports.
446+
///
447+
/// Typical values are:
448+
/// - `__llvm_covfun` on Linux
449+
/// - `__LLVM_COV,__llvm_covfun` on macOS (includes `__LLVM_COV,` segment prefix)
450+
/// - `.lcovfun$M` on Windows (includes `$M` sorting suffix)
451+
pub(crate) fn covfun_section_name(cx: &CodegenCx<'_, '_>) -> String {
452+
llvm::build_string(|s| unsafe {
453+
llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s);
454+
})
455+
.expect("Rust Coverage function record section name failed UTF-8 conversion")
456+
}

compiler/rustc_error_messages/src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,14 @@ impl MultiSpan {
533533
pub fn has_span_labels(&self) -> bool {
534534
self.span_labels.iter().any(|(sp, _)| !sp.is_dummy())
535535
}
536+
537+
/// Clone this `MultiSpan` without keeping any of the span labels - sometimes a `MultiSpan` is
538+
/// to be re-used in another diagnostic, but includes `span_labels` which have translated
539+
/// messages. These translated messages would fail to translate without their diagnostic
540+
/// arguments which are unlikely to be cloned alongside the `Span`.
541+
pub fn clone_ignoring_labels(&self) -> Self {
542+
Self { primary_spans: self.primary_spans.clone(), ..MultiSpan::new() }
543+
}
536544
}
537545

538546
impl From<Span> for MultiSpan {

compiler/rustc_errors/src/diagnostic_impls.rs

+6
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,12 @@ impl IntoDiagnosticArg for hir::ConstContext {
164164
}
165165
}
166166

167+
impl IntoDiagnosticArg for ast::Expr {
168+
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
169+
DiagnosticArgValue::Str(Cow::Owned(pprust::expr_to_string(&self)))
170+
}
171+
}
172+
167173
impl IntoDiagnosticArg for ast::Path {
168174
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
169175
DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(&self)))

compiler/rustc_hir_typeck/src/demand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5353
|| self.suggest_no_capture_closure(err, expected, expr_ty)
5454
|| self.suggest_boxing_when_appropriate(err, expr.span, expr.hir_id, expected, expr_ty)
5555
|| self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
56-
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
56+
|| self.suggest_copied_cloned_or_as_ref(err, expr, expr_ty, expected, expected_ty_expr)
5757
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
5858
|| self.suggest_into(err, expr, expr_ty, expected)
5959
|| self.suggest_floating_point_literal(err, expr, expected)

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -1085,12 +1085,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10851085
false
10861086
}
10871087

1088-
pub(crate) fn suggest_copied_or_cloned(
1088+
pub(crate) fn suggest_copied_cloned_or_as_ref(
10891089
&self,
10901090
diag: &mut Diagnostic,
10911091
expr: &hir::Expr<'_>,
10921092
expr_ty: Ty<'tcx>,
10931093
expected_ty: Ty<'tcx>,
1094+
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
10941095
) -> bool {
10951096
let ty::Adt(adt_def, args) = expr_ty.kind() else {
10961097
return false;
@@ -1102,7 +1103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11021103
return false;
11031104
}
11041105

1105-
let mut suggest_copied_or_cloned = || {
1106+
let mut suggest_copied_cloned_or_as_ref = || {
11061107
let expr_inner_ty = args.type_at(0);
11071108
let expected_inner_ty = expected_args.type_at(0);
11081109
if let &ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
@@ -1119,6 +1120,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11191120
Applicability::MachineApplicable,
11201121
);
11211122
return true;
1123+
} else if let Some(expected_ty_expr) = expected_ty_expr {
1124+
diag.span_suggestion_verbose(
1125+
expected_ty_expr.span.shrink_to_hi(),
1126+
format!(
1127+
"use `{def_path}::as_ref()` to convert `{expected_ty}` to `{expr_ty}`"
1128+
),
1129+
".as_ref()",
1130+
Applicability::MachineApplicable,
1131+
);
1132+
return true;
11221133
} else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
11231134
&& rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
11241135
self,
@@ -1146,11 +1157,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11461157
// Check that the error types are equal
11471158
&& self.can_eq(self.param_env, args.type_at(1), expected_args.type_at(1))
11481159
{
1149-
return suggest_copied_or_cloned();
1160+
return suggest_copied_cloned_or_as_ref();
11501161
} else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option)
11511162
&& adt_def.did() == option_did
11521163
{
1153-
return suggest_copied_or_cloned();
1164+
return suggest_copied_cloned_or_as_ref();
11541165
}
11551166

11561167
false

compiler/rustc_session/messages.ftl

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ session_int_literal_too_large = integer literal is too large
4545
.note = value exceeds limit of `{$limit}`
4646
4747
session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}`
48+
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
4849
4950
session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
5051
.label = invalid suffix `{$suffix}`

compiler/rustc_session/src/errors.rs

+8
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,14 @@ pub struct InvalidCharacterInCrateName {
199199
pub span: Option<Span>,
200200
pub character: char,
201201
pub crate_name: Symbol,
202+
#[subdiagnostic]
203+
pub crate_name_help: Option<InvalidCrateNameHelp>,
204+
}
205+
206+
#[derive(Subdiagnostic)]
207+
pub enum InvalidCrateNameHelp {
208+
#[help(session_invalid_character_in_create_name_help)]
209+
AddCrateName,
202210
}
203211

204212
#[derive(Subdiagnostic)]

0 commit comments

Comments
 (0)