Skip to content

Rollup of 7 pull requests #114063

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
01f3cc1
coverage: Obtain the `__llvm_covfun` section name outside a per-funct…
Zalathar Jul 24, 2023
c06a7eb
builtin_macros: expect raw strings too
davidtwco Jul 24, 2023
3857d9c
borrowck/errors: fix i18n error in delayed bug
davidtwco Jul 24, 2023
40dd5a3
docs(LazyLock): add example pass local LazyLock variable to struct
cathaysia Jul 25, 2023
75df62d
builtin_macros: raw str in diagnostic output
davidtwco Jul 25, 2023
5d32fd1
Add regression test for invalid unused const in method
Enselic Jul 25, 2023
516a565
clippy: `env!` invocations can't be b"" literals
davidtwco Jul 25, 2023
c83dfe9
Suggest `{Option,Result}::as_ref()` instead of `cloned()` in some cases
clubby789 Jul 25, 2023
037b274
abi: unsized field in union - assert to delay bug
davidtwco Jul 25, 2023
e0c479e
Add help for crate arg when crate name is invalid
chenyukang Jul 24, 2023
24e34e2
Rollup merge of #114008 - Zalathar:covfun-section-name, r=cjgillot
matthiaskrgr Jul 25, 2023
8ecaf2a
Rollup merge of #114014 - davidtwco:issue-114010-env-rawstr, r=cjgillot
matthiaskrgr Jul 25, 2023
91d1d7a
Rollup merge of #114043 - cathaysia:doc_lazy_lock, r=thomcc
matthiaskrgr Jul 25, 2023
99f404a
Rollup merge of #114051 - Enselic:const-local-var, r=cjgillot
matthiaskrgr Jul 25, 2023
b7a1ff2
Rollup merge of #114052 - clubby789:suggest-option-asref, r=WaffleLapkin
matthiaskrgr Jul 25, 2023
de5228e
Rollup merge of #114058 - chenyukang:yukang-fix-113981-crate-arg, r=f…
matthiaskrgr Jul 25, 2023
ba6982b
Rollup merge of #114060 - davidtwco:issue-113279, r=wesleywiser
matthiaskrgr Jul 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion compiler/rustc_abi/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_builtin_macros/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
43 changes: 24 additions & 19 deletions compiler/rustc_builtin_macros/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -76,41 +76,46 @@ 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),
};
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
}
}
52 changes: 26 additions & 26 deletions compiler/rustc_builtin_macros/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand Down
28 changes: 21 additions & 7 deletions compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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")
}
8 changes: 8 additions & 0 deletions compiler/rustc_error_messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_errors/src/diagnostic_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
19 changes: 15 additions & 4 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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()
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_session/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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}`
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_session/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
Loading