Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5aa5e40
Expand an early return case in `coerce_unsized`
nnethercote Oct 15, 2026
3952413
Narrow the scope of a `commit_if_ok`
nnethercote Oct 15, 2026
771d9a1
Add supporting APIs for MIR storage reconstruction
Amanieu Sep 23, 2026
72ffc10
use adaptive sparse encoding for metadata tables
TaKO8Ki Oct 17, 2026
de21c98
reduce sparse metadata table lookup overhead
TaKO8Ki Oct 22, 2026
5afdb7a
factor out lint name
mejrs Oct 15, 2026
123d20d
edit check_lint_name to accept LintName
mejrs Oct 15, 2026
6a3df09
use Lintname in lint machinery
mejrs Oct 15, 2026
f6f8683
store Lintname in error types
mejrs Oct 16, 2026
09a5060
Use LintName in LintLevelSource
mejrs Oct 17, 2026
a8a0f42
Use LintName more
mejrs Oct 18, 2026
232a750
return tool_name in NoTool error
mejrs Oct 18, 2026
361557a
clarify lint emptyness
mejrs Oct 26, 2026
5156c51
Move lang item collection to the resolver
oli-obk Jul 9, 2026
0827b4d
Reconstruct storage lifetimes after move elimination
Amanieu Sep 23, 2026
1ef87c6
do not prefer trivially true candidates
lcnr Oct 28, 2026
614730d
Don't hardcode basic block names in hint codegen tests
Amanieu Sep 26, 2026
9f6141e
Initialize ZST results in MIR construction and lowering
Amanieu Sep 25, 2026
a1136b1
SimplifyMatch: evaluate all constants instead of just scalars
Amanieu Sep 25, 2026
dfe80b8
Preserve direct ZST writes in RemoveZsts
Amanieu Sep 25, 2026
7350c9f
Ignore ZST assignments in the inliner cost model
Amanieu Sep 26, 2026
6a099dc
Rollup merge of #163339 - Amanieu:move-elimination/storage-reconstruc…
JonathanBrouwer Oct 31, 2026
97242ef
Rollup merge of #163359 - Amanieu:move-elimination/zst-initialization…
JonathanBrouwer Oct 31, 2026
3cb4b76
Rollup merge of #163525 - oli-obk:resolver_lang_items, r=petrochenkov
JonathanBrouwer Oct 31, 2026
923635a
Rollup merge of #163928 - lcnr:only-merge-eq-modulo-regions, r=BoxyUwU
JonathanBrouwer Oct 31, 2026
2acafdf
Rollup merge of #164341 - nnethercote:coerce_unsized-early-return, r=…
JonathanBrouwer Oct 31, 2026
026faeb
Rollup merge of #164484 - TaKO8Ki:sparse-metadata-tables, r=nnethercote
JonathanBrouwer Oct 31, 2026
64a8aa5
Rollup merge of #164607 - mejrs:lint_name, r=JonathanBrouwer
JonathanBrouwer Oct 31, 2026
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
2 changes: 1 addition & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4658,7 +4658,6 @@ dependencies = [
"rustc_ast_lowering",
"rustc_attr_ir",
"rustc_attr_parsing",
"rustc_crate_store",
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
Expand Down Expand Up @@ -4783,6 +4782,7 @@ dependencies = [
"rustc_ast_pretty",
"rustc_attr_ir",
"rustc_attr_parsing",
"rustc_crate_store",
"rustc_data_structures",
"rustc_errors",
"rustc_expand",
Expand Down
26 changes: 10 additions & 16 deletions compiler/rustc_attr_ir/src/lint.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use rustc_macros::{Decodable, Encodable, PrintAttribute, StableHash};
use rustc_span::{Ident, Span, Symbol, sym};
use rustc_span::{Span, Symbol, sym};
use rustc_structures::LintName;

use crate::{HashIgnoredAttrId, PrintAttribute};

#[derive(Clone, Copy, Debug, StableHash, Encodable, Decodable, PrintAttribute)]
pub enum LintCheckKind {
Allow,
Expand Down Expand Up @@ -43,21 +45,7 @@ impl LintCheckKind {
/// ```
#[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)]
pub struct LintCheck {
/// The lint's tool name, if present.
pub tool: Option<Ident>,
/// The lint's name, minus the tool name if any.
///
/// For example:
/// - `clippy::blah` -> `blah`
/// - `unstable_imports` -> `unstable_imports`
/// - `custom_tool::blah::bleh` -> `blah::bleh`
pub lint_name: Symbol,
/// The span of the lint name.
///
/// For example `#[deny(foo, bar, reason = "reason")]`
/// produces multiple `LintCheck`s, one with a span pointing to `foo`
/// and another pointing to `bar`.
pub lint_span: Span,
pub lint_name: LintName,
pub kind: LintCheckKind,
pub reason: Option<Symbol>,
/// Needed by `LintExpectationId` to track fulfilled expectations
Expand All @@ -68,4 +56,10 @@ pub struct LintCheck {
/// inside one attribute are all smooshed and flattened together, so
/// multiple `LintCheck`s can have the same `attr_span`.
pub attr_span: Span,
/// The span of the entire lint name.
///
/// #[deny(foo::bar::baz)]
/// ^^^^^^^^^^^^^
pub lint_span: Span,
pub tool_span: Option<Span>,
}
5 changes: 4 additions & 1 deletion compiler/rustc_attr_ir/src/pretty_printing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_span::def_id::DefId;
use rustc_span::hygiene::Transparency;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
use rustc_structures::{CollapseMacroDebuginfo, CrateType, Limit, NativeLibKind, SanitizerSet};
use rustc_structures::{
CollapseMacroDebuginfo, CrateType, Limit, LintName, NativeLibKind, SanitizerSet,
};
use thin_vec::ThinVec;

use crate::HashIgnoredAttrId;
Expand Down Expand Up @@ -223,4 +225,5 @@ print_debug!(
CrateType,
NativeLibKind,
CollapseMacroDebuginfo,
LintName,
);
46 changes: 17 additions & 29 deletions compiler/rustc_attr_parsing/src/attributes/lint.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use rustc_ast::join_path_syms;
use rustc_attr_ir::AttributeKind;
use rustc_attr_ir::lint::{LintCheck, LintCheckKind};
use rustc_attr_ir::target::{AssocCtxt, MethodKind, Target};
use rustc_lint_defs::builtin::UNUSED_ATTRIBUTES;
use rustc_span::{Symbol, sym};
use rustc_span::sym;
use rustc_structures::LintName;
use thin_vec::ThinVec;

use crate::attributes::{AcceptMapping, AttributeParser, AttributeStability};
Expand Down Expand Up @@ -52,33 +52,21 @@ impl LintParser {
match item {
MetaItemOrLitParser::MetaItemParser(p) => {
match p.args() {
ArgParser::NoArgs => {
let (tool, lint_name) = match &*p.path().0.segments {
[] => unreachable!(),
[lint_name] => (None, lint_name.ident.name),
[tool, lint_name] => (Some(tool.ident), lint_name.ident.name),
// Not reachable for any builtin lints,
// but reachable using `register_tool`.
[tool, multi_segment_lint_name @ ..] => (
Some(tool.ident),
Symbol::intern(&join_path_syms(
multi_segment_lint_name
.iter()
.map(|seg| seg.ident.name),
)),
),
};

self.lints.push(LintCheck {
tool,
lint_name,
lint_span: p.span(),
kind,
attr_id,
reason,
attr_span,
})
}
ArgParser::NoArgs => self.lints.push(LintCheck {
lint_name: LintName::new(
p.path().0.segments.iter().map(|s| s.ident.name),
),
kind,
attr_id,
reason,
attr_span,
lint_span: p.span(),
tool_span: if let [tool, _, ..] = &*p.path().0.segments {
Some(tool.span())
} else {
None
},
}),
// We've found a `reason = "reason"` but we're not the last element.
ArgParser::NameValue(nv) if p.path().word_is(sym::reason) => {
cx.emit_err(diagnostics::MalformedAttribute {
Expand Down
14 changes: 6 additions & 8 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ use rustc_session::output::invalid_output_for_target;
use rustc_session::{EarlyDiagCtxt, Session, config};
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::{DUMMY_SP, FileName};
use rustc_structures::CrateType;
use rustc_structures::{CrateType, LintName};
use rustc_target::json::ToJson;
use rustc_target::spec::{Target, TargetTuple};
use tracing::trace;
Expand Down Expand Up @@ -990,11 +990,9 @@ Available lint options:
lints
}

fn sort_lint_groups(
lints: Vec<(&'static str, Vec<LintId>, bool)>,
) -> Vec<(&'static str, Vec<LintId>)> {
fn sort_lint_groups(lints: Vec<(LintName, Vec<LintId>, bool)>) -> Vec<(LintName, Vec<LintId>)> {
let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
lints.sort_by_key(|l| l.0);
lints.sort_by(|left, right| Ord::cmp(&left.0, &right.0));
lints
}

Expand Down Expand Up @@ -1041,7 +1039,7 @@ Available lint options:
loaded_groups
.iter()
.chain(&builtin_groups)
.map(|&(s, _)| s.chars().count())
.map(|(s, _)| s.name.as_str().chars().count())
.max()
.unwrap_or(0),
);
Expand All @@ -1054,7 +1052,7 @@ Available lint options:

safe_println!("Lint groups provided by rustc:\n");

let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>, all_warnings| {
let print_lint_groups = |lints: Vec<(LintName, Vec<LintId>)>, all_warnings| {
safe_println!(" {} sub-lints", padded("name"));
safe_println!(" {} ---------", padded("----"));

Expand All @@ -1063,7 +1061,7 @@ Available lint options:
}

for (name, to) in lints {
let name = name.to_lowercase().replace('_', "-");
let name = name.to_string().to_lowercase().replace('_', "-");
let desc = to
.into_iter()
.map(|x| x.to_string().replace('_', "-"))
Expand Down
179 changes: 97 additions & 82 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}

// Consider coercing the subtype to a DST
//
// NOTE: this is wrapped in a `commit_if_ok` because it creates
// a "spurious" type variable, and we don't want to have that
// type variable in memory if the coercion fails.
let unsize = self.commit_if_ok(|_| self.coerce_unsized(a, b));
let unsize = self.coerce_unsized(a, b);
match unsize {
Ok(_) => {
debug!("coerce: unsize successful");
Expand Down Expand Up @@ -589,8 +585,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// and call arg (among other positions).
//
// These targets are known to never be RHS in `LHS: CoerceUnsized<RHS>`.
// That's because these are built-in types for which a core-provided impl
// doesn't exist, and for which a user-written impl is invalid.
// That's because one of the following is true.
// - For the built-in types, a core-provided impl doesn't exist and a
// user-written impl is invalid.
// - For enums and unions, they can never be the target of a
// `CoerceUnsized` impl.
// - For structs, they can only be the target of a `CoerceUnsized` impl
// if `LHS` and `RHS` are instances of the same struct type but with
// at least one differing field type. This is impossible when we
// exclude structs with any generic args.
//
// This is technically incomplete when users write impossible bounds like
// `where T: CoerceUnsized<usize>`, for example, but that trait is unstable
Expand Down Expand Up @@ -619,6 +622,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
| ty::CoroutineWitness(_, _)
| ty::Never
| ty::Tuple(_) => return Err(TypeError::Mismatch),
ty::Adt(adt, args) => match adt.adt_kind() {
ty::AdtKind::Enum | ty::AdtKind::Union => return Err(TypeError::Mismatch),
ty::AdtKind::Struct if args.is_empty() => return Err(TypeError::Mismatch),
_ => {}
},
_ => {}
}
// `&str: CoerceUnsized<&str>` does not hold but is encountered frequently
Expand All @@ -642,85 +650,92 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// a DST unless we have to. This currently comes out in the wash since
// we can't unify [T] with U. But to properly support DST, we need to allow
// that, at which point we will need extra checks on the target here.
//
// NOTE: this is wrapped in a `commit_if_ok` because it creates
// a "spurious" type variable, and we don't want to have that
// type variable in memory if the coercion fails.
self.commit_if_ok(|_| {
// Handle reborrows before selecting `Source: CoerceUnsized<Target>`.
let reborrow = match (source.kind(), target.kind()) {
(&ty::Ref(_, ty_a, mutbl_a), &ty::Ref(_, _, mutbl_b)) => {
coerce_mutbls(mutbl_a, mutbl_b)?;

// Handle reborrows before selecting `Source: CoerceUnsized<Target>`.
let reborrow = match (source.kind(), target.kind()) {
(&ty::Ref(_, ty_a, mutbl_a), &ty::Ref(_, _, mutbl_b)) => {
coerce_mutbls(mutbl_a, mutbl_b)?;

let coercion = RegionVariableOrigin::Coercion(self.cause.span);
let r_borrow = self.next_region_var(coercion);

// We don't allow two-phase borrows here, at least for initial
// implementation. If it happens that this coercion is a function argument,
// the reborrow in coerce_borrowed_ptr will pick it up.
let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No);

Some((
Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: ty_a },
Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
target: Ty::new_ref(self.tcx, r_borrow, ty_a, mutbl_b),
},
))
}
(&ty::Ref(_, ty_a, mt_a), &ty::RawPtr(_, mt_b)) => {
coerce_mutbls(mt_a, mt_b)?;

Some((
Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: ty_a },
Adjustment {
kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)),
target: Ty::new_ptr(self.tcx, ty_a, mt_b),
},
))
}
_ => None,
};
let coerce_source = reborrow.as_ref().map_or(source, |(_, r)| r.target);

// Setup either a subtyping or a LUB relationship between
// the `CoerceUnsized` target type and the expected type.
// We only have the latter, so we use an inference variable
// for the former and let type inference do the rest.
let coerce_target = self.next_ty_var(self.cause.span);

let mut coercion = self.unify_and(
coerce_target,
target,
reborrow.map(|(deref, autoref)| [deref, autoref]).into_flat_iter(),
Adjust::Pointer(PointerCoercion::Unsize),
ForceLeakCheck::No,
)?;

// Create an obligation for `Source: CoerceUnsized<Target>`.
let cause = self.cause(self.cause.span, ObligationCauseCode::Coercion { source, target });
let pred = ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]);
let obligation = Obligation::new(self.tcx, cause, self.fcx.param_env, pred);

if self.next_trait_solver() {
coercion.obligations.push(obligation);
let coercion = RegionVariableOrigin::Coercion(self.cause.span);
let r_borrow = self.next_region_var(coercion);

// We don't allow two-phase borrows here, at least for initial
// implementation. If it happens that this coercion is a function argument,
// the reborrow in coerce_borrowed_ptr will pick it up.
let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No);

Some((
Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: ty_a },
Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
target: Ty::new_ref(self.tcx, r_borrow, ty_a, mutbl_b),
},
))
}
(&ty::Ref(_, ty_a, mt_a), &ty::RawPtr(_, mt_b)) => {
coerce_mutbls(mt_a, mt_b)?;

Some((
Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: ty_a },
Adjustment {
kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)),
target: Ty::new_ptr(self.tcx, ty_a, mt_b),
},
))
}
_ => None,
};
let coerce_source = reborrow.as_ref().map_or(source, |(_, r)| r.target);

// Setup either a subtyping or a LUB relationship between
// the `CoerceUnsized` target type and the expected type.
// We only have the latter, so we use an inference variable
// for the former and let type inference do the rest.
let coerce_target = self.next_ty_var(self.cause.span);

let mut coercion = self.unify_and(
coerce_target,
target,
reborrow.map(|(deref, autoref)| [deref, autoref]).into_flat_iter(),
Adjust::Pointer(PointerCoercion::Unsize),
ForceLeakCheck::No,
)?;

if self
.infcx
.visit_proof_tree(
Goal::new(self.tcx, self.param_env, pred),
&mut CoerceVisitor { fcx: self.fcx, span: self.cause.span, errored: false },
)
.is_break()
{
return Err(TypeError::Mismatch);
// Create an obligation for `Source: CoerceUnsized<Target>`.
let cause =
self.cause(self.cause.span, ObligationCauseCode::Coercion { source, target });
let pred =
ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]);
let obligation = Obligation::new(self.tcx, cause, self.fcx.param_env, pred);

if self.next_trait_solver() {
coercion.obligations.push(obligation);

if self
.infcx
.visit_proof_tree(
Goal::new(self.tcx, self.param_env, pred),
&mut CoerceVisitor { fcx: self.fcx, span: self.cause.span, errored: false },
)
.is_break()
{
return Err(TypeError::Mismatch);
}
} else {
self.coerce_unsized_old_solver(
obligation,
&mut coercion,
coerce_unsized_did,
unsize_did,
)?;
}
} else {
self.coerce_unsized_old_solver(
obligation,
&mut coercion,
coerce_unsized_did,
unsize_did,
)?;
}

Ok(coercion)
Ok(coercion)
})
}

fn coerce_unsized_old_solver(
Expand Down
Loading
Loading