Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
b476969
Allow unnormalized types in drop elaboration
Nadrieril Nov 9, 2025
e9ed626
Add support for variant fields in `rustdoc::html::format::print_anchor`
GuillaumeGomez Nov 17, 2025
a5f972e
Remove `UrlFragment::render` method to unify `clean::types::links` an…
GuillaumeGomez Nov 17, 2025
ed6a78c
Fix error message for calling a non-tuple struct
Jamesbarford Nov 19, 2025
8c569c1
run-make-support: re-export rustdoc_json_types
aDotInTheVoid Nov 19, 2025
3d33942
Use less brittle way for updating error message
Jamesbarford Nov 20, 2025
361af82
rustdoc-json: add rlib path to ExternalCrate to enable robust crate r…
aDotInTheVoid Nov 17, 2025
fc822f8
Emit error when using path-segment keyword as cfg pred
mu001999 Oct 16, 2025
640990f
Add test for importing path-segment keyword
mu001999 Nov 20, 2025
6e63c39
feat: add rust.rustflags and per target rustflags options to bootstra…
karolzwolak Nov 10, 2025
8f76773
Return `impl Display` instead of `String` in `fragment`
GuillaumeGomez Nov 20, 2025
33d11ef
Rollup merge of #146978 - mu001999-contrib:fix/path-kw-as-cfg-pred, r…
GuillaumeGomez Nov 21, 2025
60ed1ab
Rollup merge of #148719 - Nadrieril:poly-drop-glue, r=saethlin
GuillaumeGomez Nov 21, 2025
8d66eb5
Rollup merge of #148795 - karolzwolak:rustflags-bootstrap-toml, r=Kobzol
GuillaumeGomez Nov 21, 2025
110471b
Rollup merge of #149028 - GuillaumeGomez:unify-anchor, r=lolbinarycat
GuillaumeGomez Nov 21, 2025
629a283
Rollup merge of #149043 - aDotInTheVoid:is-this-real-is-this-out-of-s…
GuillaumeGomez Nov 21, 2025
b2f5cc7
Rollup merge of #149098 - Jamesbarford:fix/148919-tuple-struct-lint, …
GuillaumeGomez Nov 21, 2025
228b49e
Rollup merge of #149151 - mu001999-contrib:test/use-path-kw, r=petroc…
GuillaumeGomez Nov 21, 2025
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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3336,6 +3336,7 @@ dependencies = [
"libc",
"object 0.37.3",
"regex",
"rustdoc-json-types",
"serde_json",
"similar",
"wasmparser 0.236.1",
Expand Down
12 changes: 12 additions & 0 deletions bootstrap.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,12 @@
# desired in distributions, for example.
#rust.rpath = true

# Additional flags to pass to `rustc`.
# Takes precedence over bootstrap's own flags but not over per target rustflags nor env. vars. like RUSTFLAGS.
# Applies to all stages and targets.
#
#rust.rustflags = []

# Indicates whether symbols should be stripped using `-Cstrip=symbols`.
#rust.strip = false

Expand Down Expand Up @@ -1013,6 +1019,12 @@
# and will override the same option under [rust] section. It only works on Unix platforms
#rpath = rust.rpath (bool)

# Additional flags to pass to `rustc`.
# Takes precedence over bootstrap's own flags and `rust.rustflags` but not over env. vars. like RUSTFLAGS.
# Applies to all stages.
#
#rustflags = rust.rustflags

# Force static or dynamic linkage of the standard library for this target. If
# this target is a host for rustc, this will also affect the linkage of the
# compiler itself. This is useful for building rustc on targets that normally
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ pub fn parse_cfg_entry<S: Stage>(
}
},
a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => {
let Some(name) = meta.path().word_sym() else {
let Some(name) = meta.path().word_sym().filter(|s| !s.is_path_segment_keyword())
else {
return Err(cx.expected_identifier(meta.path().span()));
};
parse_name_value(name, meta.path().span(), a.name_value(), meta.span(), cx)?
Expand Down Expand Up @@ -158,7 +159,7 @@ fn parse_cfg_entry_target<S: Stage>(
};

// Then, parse it as a name-value item
let Some(name) = sub_item.path().word_sym() else {
let Some(name) = sub_item.path().word_sym().filter(|s| !s.is_path_segment_keyword()) else {
return Err(cx.expected_identifier(sub_item.path().span()));
};
let name = Symbol::intern(&format!("target_{name}"));
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_attr_parsing/src/attributes/cfg_old.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,10 @@ pub fn eval_condition(
}
}
}
MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
MetaItemKind::Word | MetaItemKind::NameValue(..)
if cfg.path.segments.len() != 1
|| cfg.path.segments[0].ident.is_path_segment_keyword() =>
{
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
true
}
Expand Down
22 changes: 8 additions & 14 deletions compiler/rustc_errors/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,30 +532,24 @@ impl Emitter for HumanEmitter {
}
}

/// An emitter that does nothing when emitting a non-fatal diagnostic.
/// Fatal diagnostics are forwarded to `fatal_emitter` to avoid silent
/// failures of rustc, as witnessed e.g. in issue #89358.
pub struct FatalOnlyEmitter {
pub fatal_emitter: Box<dyn Emitter + DynSend>,
pub fatal_note: Option<String>,
/// An emitter that adds a note to each diagnostic.
pub struct EmitterWithNote {
pub emitter: Box<dyn Emitter + DynSend>,
pub note: String,
}

impl Emitter for FatalOnlyEmitter {
impl Emitter for EmitterWithNote {
fn source_map(&self) -> Option<&SourceMap> {
None
}

fn emit_diagnostic(&mut self, mut diag: DiagInner, registry: &Registry) {
if diag.level == Level::Fatal {
if let Some(fatal_note) = &self.fatal_note {
diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new());
}
self.fatal_emitter.emit_diagnostic(diag, registry);
}
diag.sub(Level::Note, self.note.clone(), MultiSpan::new());
self.emitter.emit_diagnostic(diag, registry);
}

fn translator(&self) -> &Translator {
self.fatal_emitter.translator()
self.emitter.translator()
}
}

Expand Down
70 changes: 44 additions & 26 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use rustc_middle::ty::CurrentGcx;
use rustc_middle::util::Providers;
use rustc_parse::lexer::StripTokens;
use rustc_parse::new_parser_from_source_str;
use rustc_parse::parser::Recovery;
use rustc_parse::parser::attr::AllowLeadingUnsafe;
use rustc_query_impl::QueryCtxt;
use rustc_query_system::query::print_query_stack;
Expand Down Expand Up @@ -52,46 +53,56 @@ pub struct Compiler {
pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
cfgs.into_iter()
.map(|s| {
let psess = ParseSess::with_fatal_emitter(
let psess = ParseSess::emitter_with_note(
vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
format!("this error occurred on the command line: `--cfg={s}`"),
format!("this occurred on the command line: `--cfg={s}`"),
);
let filename = FileName::cfg_spec_source_code(&s);

macro_rules! error {
($reason: expr) => {
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
dcx.fatal(format!(
concat!("invalid `--cfg` argument: `{}` (", $reason, ")"),
s
));
dcx.fatal(format!("invalid `--cfg` argument: `{s}` ({})", $reason));
};
}

match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing)
{
Ok(mut parser) => match parser.parse_meta_item(AllowLeadingUnsafe::No) {
Ok(meta_item) if parser.token == token::Eof => {
if meta_item.path.segments.len() != 1 {
error!("argument key must be an identifier");
}
match &meta_item.kind {
MetaItemKind::List(..) => {}
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
error!("argument value must be a string");
Ok(mut parser) => {
parser = parser.recovery(Recovery::Forbidden);
match parser.parse_meta_item(AllowLeadingUnsafe::No) {
Ok(meta_item)
if parser.token == token::Eof
&& parser.dcx().has_errors().is_none() =>
{
if meta_item.path.segments.len() != 1 {
error!("argument key must be an identifier");
}
MetaItemKind::NameValue(..) | MetaItemKind::Word => {
let ident = meta_item.ident().expect("multi-segment cfg key");
return (ident.name, meta_item.value_str());
match &meta_item.kind {
MetaItemKind::List(..) => {}
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
error!("argument value must be a string");
}
MetaItemKind::NameValue(..) | MetaItemKind::Word => {
let ident = meta_item.ident().expect("multi-segment cfg key");

if ident.is_path_segment_keyword() {
error!(
"malformed `cfg` input, expected a valid identifier"
);
}

return (ident.name, meta_item.value_str());
}
}
}
Ok(..) => {}
Err(err) => err.cancel(),
}
Ok(..) => {}
Err(err) => err.cancel(),
},
}
Err(errs) => errs.into_iter().for_each(|err| err.cancel()),
}
};

// If the user tried to use a key="value" flag, but is missing the quotes, provide
// a hint about how to resolve this.
Expand All @@ -116,9 +127,9 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() };

for s in specs {
let psess = ParseSess::with_fatal_emitter(
let psess = ParseSess::emitter_with_note(
vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
format!("this error occurred on the command line: `--check-cfg={s}`"),
format!("this occurred on the command line: `--check-cfg={s}`"),
);
let filename = FileName::cfg_spec_source_code(&s);

Expand Down Expand Up @@ -171,15 +182,17 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
let mut parser =
match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing)
{
Ok(parser) => parser,
Ok(parser) => parser.recovery(Recovery::Forbidden),
Err(errs) => {
errs.into_iter().for_each(|err| err.cancel());
expected_error();
}
};

let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::No) {
Ok(meta_item) if parser.token == token::Eof => meta_item,
Ok(meta_item) if parser.token == token::Eof && parser.dcx().has_errors().is_none() => {
meta_item
}
Ok(..) => expected_error(),
Err(err) => {
err.cancel();
Expand Down Expand Up @@ -209,6 +222,11 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
if values_specified {
error!("`cfg()` names cannot be after values");
}

if ident.is_path_segment_keyword() {
error!("malformed `cfg` input, expected a valid identifier");
}

names.push(ident);
} else if let Some(boolean) = arg.boolean_literal() {
if values_specified {
Expand Down
19 changes: 6 additions & 13 deletions compiler/rustc_mir_transform/src/elaborate_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,19 +511,12 @@ where
let tcx = self.tcx();

assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis);
let field_ty = match tcx.try_normalize_erasing_regions(
self.elaborator.typing_env(),
field.ty(tcx, args),
) {
Ok(t) => t,
Err(_) => Ty::new_error(
self.tcx(),
self.tcx().dcx().span_delayed_bug(
self.elaborator.body().span,
"Error normalizing in drop elaboration.",
),
),
};
let field_ty = field.ty(tcx, args);
// We silently leave an unnormalized type here to support polymorphic drop
// elaboration for users of rustc internal APIs
let field_ty = tcx
.try_normalize_erasing_regions(self.elaborator.typing_env(), field_ty)
.unwrap_or(field_ty);

(tcx.mk_place_field(base_place, field_idx, field_ty), subpath)
})
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ impl<'a> Parser<'a> {

// Public for rustfmt usage.
pub fn parse_ident(&mut self) -> PResult<'a, Ident> {
self.parse_ident_common(true)
self.parse_ident_common(self.may_recover())
}

fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, Ident> {
Expand Down
27 changes: 24 additions & 3 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,8 +823,16 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
}

if let Some(Res::Def(DefKind::Struct, def_id)) = res {
self.update_err_for_private_tuple_struct_fields(err, &source, def_id);
err.note("constructor is not visible here due to private fields");
let private_fields = self.has_private_fields(def_id);
let adjust_error_message =
private_fields && self.is_struct_with_fn_ctor(def_id);
if adjust_error_message {
self.update_err_for_private_tuple_struct_fields(err, &source, def_id);
}

if private_fields {
err.note("constructor is not visible here due to private fields");
}
} else {
err.span_suggestion(
call_span,
Expand Down Expand Up @@ -1642,6 +1650,19 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
}
}

fn is_struct_with_fn_ctor(&mut self, def_id: DefId) -> bool {
def_id
.as_local()
.and_then(|local_id| self.r.struct_constructors.get(&local_id))
.map(|struct_ctor| {
matches!(
struct_ctor.0,
def::Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), _)
)
})
.unwrap_or(false)
}

fn update_err_for_private_tuple_struct_fields(
&mut self,
err: &mut Diag<'_>,
Expand Down Expand Up @@ -1674,7 +1695,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
*call_span,
&args[..],
);
// Use spans of the tuple struct definition.

self.r
.field_idents(def_id)
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
Expand Down
12 changes: 4 additions & 8 deletions compiler/rustc_session/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_ast::attr::AttrIdGenerator;
use rustc_ast::node_id::NodeId;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::sync::{AppendOnlyVec, Lock};
use rustc_errors::emitter::{FatalOnlyEmitter, HumanEmitter, stderr_destination};
use rustc_errors::emitter::{EmitterWithNote, HumanEmitter, stderr_destination};
use rustc_errors::translation::Translator;
use rustc_errors::{
BufferedEarlyLint, ColorConfig, DecorateDiagCompat, Diag, DiagCtxt, DiagCtxtHandle,
Expand Down Expand Up @@ -315,16 +315,12 @@ impl ParseSess {
}
}

pub fn with_fatal_emitter(locale_resources: Vec<&'static str>, fatal_note: String) -> Self {
pub fn emitter_with_note(locale_resources: Vec<&'static str>, note: String) -> Self {
let translator = Translator::with_fallback_bundle(locale_resources, false);
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
let fatal_emitter =
let emitter =
Box::new(HumanEmitter::new(stderr_destination(ColorConfig::Auto), translator));
let dcx = DiagCtxt::new(Box::new(FatalOnlyEmitter {
fatal_emitter,
fatal_note: Some(fatal_note),
}))
.disable_warnings();
let dcx = DiagCtxt::new(Box::new(EmitterWithNote { emitter, note }));
ParseSess::with_dcx(dcx, sm)
}

Expand Down
16 changes: 16 additions & 0 deletions src/bootstrap/src/core/builder/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ pub struct Cargo {
allow_features: String,
release_build: bool,
build_compiler_stage: u32,
extra_rustflags: Vec<String>,
}

impl Cargo {
Expand Down Expand Up @@ -403,6 +404,11 @@ impl From<Cargo> for BootstrapCommand {
cargo.args.insert(0, "--release".into());
}

for arg in &cargo.extra_rustflags {
cargo.rustflags.arg(arg);
cargo.rustdocflags.arg(arg);
}

// Propagate the envs here at the very end to make sure they override any previously set flags.
cargo.rustflags.propagate_rustflag_envs(cargo.build_compiler_stage);
cargo.rustdocflags.propagate_rustflag_envs(cargo.build_compiler_stage);
Expand Down Expand Up @@ -1379,6 +1385,15 @@ impl Builder<'_> {
rustflags.arg("-Zmir_strip_debuginfo=locals-in-tiny-functions");
}

// take target-specific extra rustflags if any otherwise take `rust.rustflags`
let extra_rustflags = self
.config
.target_config
.get(&target)
.map(|t| &t.rustflags)
.unwrap_or(&self.config.rust_rustflags)
.clone();

let release_build = self.config.rust_optimize.is_release() &&
// cargo bench/install do not accept `--release` and miri doesn't want it
!matches!(cmd_kind, Kind::Bench | Kind::Install | Kind::Miri | Kind::MiriSetup | Kind::MiriTest);
Expand All @@ -1394,6 +1409,7 @@ impl Builder<'_> {
allow_features,
release_build,
build_compiler_stage,
extra_rustflags,
}
}
}
Expand Down
Loading
Loading