Skip to content
Closed
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
f7548dd
Stabilize `funnel_shifts` (including `const`)
tgross35 Aug 13, 2026
452a7ca
make `RustaceansAreAwesome` satisfy trait bounds
dianne Sep 23, 2026
b6f9bfc
Additional NonZero conversions
clarfonthey Aug 13, 2024
f3b4f0f
Stabilize `Result::into_{ok,err}`
theemathas Aug 25, 2026
188011a
test(imports): add baseline regression for hidden extern crate sugges…
raushan728 Jul 9, 2026
2e4b8e5
fix(metadata): demote unnameable `extern crate` items to `ExternCrate…
raushan728 Jul 9, 2026
26b5f90
Move `alloc::rc` into `alloc::rcs`
EFanZh Sep 28, 2026
f74f6ea
Rename `library/alloc/src/sync.rs` to `library/alloc/src/rcs/arc.rs` …
EFanZh Sep 28, 2026
cba3237
Re-export `alloc::rcs::arc::*` in `alloc::sync`
EFanZh Sep 28, 2026
2e58a77
Fix intra doc link resolution when a doc comment is composed of both …
GuillaumeGomez Sep 16, 2026
9e8ca58
implement #![feature(gca_adts)]
khyperia Sep 28, 2026
ceee44b
Force the correct type variable to never for method resolution on an …
JonathanBrouwer Sep 28, 2026
f3b6502
Run the `method-on-never` type on the next trait solver
JonathanBrouwer Sep 28, 2026
62ce017
Allow using different index types when reading and writing to tables
aerooneqq Sep 28, 2026
b6d0fb1
select: prefer impl candidates over where clauses
dianne Sep 11, 2026
047b23e
When compiling without a specified `--edition`, emit a `eprintln` mes…
estebank Jun 18, 2026
14ca74b
Rollup merge of #129036 - clarfonthey:nonzero-conversions, r=nia-e
JonathanBrouwer Sep 28, 2026
c48e803
Rollup merge of #158997 - raushan728:issues/153459, r=petrochenkov
JonathanBrouwer Sep 28, 2026
264d7ae
Rollup merge of #161015 - tgross35:stabilize-funnel-shifts, r=nia-e
JonathanBrouwer Sep 28, 2026
d4a714b
Rollup merge of #161712 - theemathas:stab-into-ok-err, r=nia-e
JonathanBrouwer Sep 28, 2026
97aaa14
Rollup merge of #162655 - dianne:drop-paramenv-candidates, r=lcnr
JonathanBrouwer Sep 28, 2026
f15d71a
Rollup merge of #162862 - GuillaumeGomez:intra-doc-link-resolution, r…
JonathanBrouwer Sep 28, 2026
4bd2368
Rollup merge of #163200 - dianne:dyn-satisfies-bounds, r=oli-obk
JonathanBrouwer Sep 28, 2026
c7a4126
Rollup merge of #163331 - EFanZh:move-arc-and-rc-into-rcs, r=tgross35
JonathanBrouwer Sep 28, 2026
f298e84
Rollup merge of #163427 - khyperia:gca-adts, r=BoxyUwU
JonathanBrouwer Sep 28, 2026
a974821
Rollup merge of #158102 - estebank:note-default-edition, r=jieyouxu
JonathanBrouwer Sep 28, 2026
cc6132a
Rollup merge of #163447 - aerooneqq:two-sided-index-in-metadata, r=pe…
JonathanBrouwer Sep 28, 2026
a0e9fea
Rollup merge of #163450 - JonathanBrouwer:fix-never, r=lcnr
JonathanBrouwer Sep 28, 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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3626,6 +3626,7 @@ dependencies = [
name = "rustc_ast_lowering"
version = "0.0.0"
dependencies = [
"bitflags",
"rustc_abi",
"rustc_ast",
"rustc_attr_ir",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_arena/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
#![allow(clippy::mut_from_ref)] // Arena allocators are one place where this pattern is fine.
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(never_type))]
#![cfg_attr(bootstrap, feature(unwrap_infallible))]
#![cfg_attr(test, feature(test))]
#![deny(unsafe_op_in_unsafe_fn)]
#![doc(test(no_crate_inject, attr(deny(warnings))))]
#![feature(decl_macro)]
#![feature(dropck_eyepatch)]
#![feature(rustc_attrs)]
#![feature(unwrap_infallible)]
// tidy-alphabetical-end

use std::alloc::Layout;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast_lowering/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ doctest = false

[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_attr_ir = { path = "../rustc_attr_ir" }
Expand Down
149 changes: 98 additions & 51 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use rustc_data_structures::steal::Steal;
use rustc_data_structures::tagged_ptr::TaggedRef;
use rustc_errors::codes::*;
use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, ErrorGuaranteed};
use rustc_hir::def::{DefKind, Namespace, PerNS, Res};
use rustc_hir::def::{CtorKind, DefKind, Namespace, PerNS, Res};
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
use rustc_hir::definitions::PerParentDisambiguatorState;
use rustc_hir::lints::DelayedLint;
Expand Down Expand Up @@ -1420,10 +1420,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
let ct = self.arena.alloc(ct);
return GenericArg::Const(ct.try_as_ambig_ct().unwrap());
}
TyKind::GcaMacro(expr) if self.tcx.features().gca_min_const_items() => {
TyKind::GcaMacro(expr) if self.tcx.features().gca() => {
let ct = match self.can_lower_expr_to_const_arg_direct(
expr,
DirectConstArgContext::MacrolessMinGenericConstArgs,
self.direct_const_arg_context_enabled_by_gca_macro(),
) {
Ok(()) => self.lower_expr_to_const_arg_direct(expr, None),
Err(e) => e.emit(self),
Expand Down Expand Up @@ -2628,18 +2628,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
span: Span,
) -> hir::ConstItemRhs<'hir> {
let is_direct = |body| {
if self.tcx.features().gca_macroless_items() {
self.can_lower_expr_to_const_arg_direct(
body,
DirectConstArgContext::MacrolessMinGenericConstArgs,
)
.is_ok()
let context = if self.tcx.features().gca_macroless_items() {
self.direct_const_arg_context_enabled_by_gca_macro()
} else {
// do not check can_lower_expr_to_const_arg_direct, but rather just
// ExprKind::GcaMacro, because we don't want e.g.
// `impl<const N: u8> { const C: u8 = N; }` to be a direct-rhs const
matches!(body, Expr { kind: ExprKind::GcaMacro(_), .. })
}
DirectConstArgContext::GCA_MACRO
};
self.can_lower_expr_to_const_arg_direct(body, context).is_ok()
};
if self.tcx.features().gca_min_const_items()
&& let Some(body) = body
Expand All @@ -2653,13 +2647,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

fn direct_const_arg_context_enabled_by_gca_macro(&self) -> DirectConstArgContext {
let mut result = DirectConstArgContext::GCA_BASE_FEATURES;
if self.tcx.features().gca_min_const_items() {
result |= DirectConstArgContext::GCA_MIN_CONST_ITEMS;
}
if self.tcx.features().gca_adts() {
result |= DirectConstArgContext::GCA_ADTS;
}
result
}

/// Only valid for const *arg* contexts, not const *item* contexts.
fn ambient_direct_const_arg_context(&self) -> DirectConstArgContext {
if self.tcx.features().gca_macroless_args() {
DirectConstArgContext::MacrolessMinGenericConstArgs
} else if self.tcx.features().gca_min_const_items() {
DirectConstArgContext::MinGenericConstArgs
self.direct_const_arg_context_enabled_by_gca_macro()
} else if self.tcx.features().gca() {
DirectConstArgContext::GCA
} else {
DirectConstArgContext::Stable
DirectConstArgContext::STABLE
}
}

Expand All @@ -2671,9 +2677,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
res: Option<Res<NodeId>>,
context: DirectConstArgContext,
) -> Result<(), UnrepresentableConstArgError> {
if let DirectConstArgContext::MacrolessMinGenericConstArgs = context {
if context.contains(DirectConstArgContext::PATH_ANY) {
Ok(())
} else if context.contains(DirectConstArgContext::PATH_CONST_CTOR)
&& matches!(res, Some(Res::Def(DefKind::Ctor(_, CtorKind::Const), _)))
{
// FIXME(gca_adts): This check is incomplete. Type-relative paths and other complicating
// factors make things very difficult - e.g. `<Option<T>>::None`
Ok(())
} else if qself.is_none()
} else if context.contains(DirectConstArgContext::PATH_PLAIN_PARAM)
&& qself.is_none()
&& path.is_single_argless_ident()
&& matches!(res, Some(Res::Def(DefKind::ConstParam, _)))
{
Expand All @@ -2689,59 +2702,61 @@ impl<'hir> LoweringContext<'_, 'hir> {
expr: &Expr,
context: DirectConstArgContext,
) -> Result<(), UnrepresentableConstArgError> {
use DirectConstArgContext::*;
// Note the only stable case is currently ExprKind::Path
match (&expr.kind, context) {
(
ExprKind::Call(Expr { kind: ExprKind::Path(_, _), .. }, args),
MacrolessMinGenericConstArgs,
) => {
match &expr.kind {
ExprKind::Call(Expr { kind: ExprKind::Path(_, _), .. }, args)
if context.contains(DirectConstArgContext::TUPLE_CALL) =>
{
for arg in args {
self.can_lower_expr_to_const_arg_direct(arg, context)?;
}
Ok(())
}
(ExprKind::Tup(exprs), MacrolessMinGenericConstArgs) => {
ExprKind::Tup(exprs) if context.contains(DirectConstArgContext::TUPLE) => {
for expr in exprs {
self.can_lower_expr_to_const_arg_direct(expr, context)?;
}
Ok(())
}
(ExprKind::Path(qself, path), _) => {
ExprKind::Path(qself, path) => {
let res =
self.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
self.can_lower_path_to_const_arg_direct(qself, path, expr.span, res, context)
}
(ExprKind::Struct(se), MacrolessMinGenericConstArgs) => {
ExprKind::Struct(se) if context.contains(DirectConstArgContext::STRUCT) => {
for f in &se.fields {
self.can_lower_expr_to_const_arg_direct(&f.expr, context)?;
}
Ok(())
}
(ExprKind::Array(elements), MacrolessMinGenericConstArgs) => {
ExprKind::Array(elements) if context.contains(DirectConstArgContext::ARRAY) => {
for element in elements {
self.can_lower_expr_to_const_arg_direct(element, context)?;
}
Ok(())
}
(ExprKind::Underscore, MacrolessMinGenericConstArgs) => Ok(()),
(ExprKind::Paren(expr), MacrolessMinGenericConstArgs) => {
ExprKind::Underscore if context.contains(DirectConstArgContext::UNDERSCORE) => Ok(()),
ExprKind::Paren(expr) if context.contains(DirectConstArgContext::PAREN) => {
self.can_lower_expr_to_const_arg_direct(expr, context)
}
(ExprKind::Block(block, _), MacrolessMinGenericConstArgs)
if let [stmt] = block.stmts.as_slice()
ExprKind::Block(block, _)
if context.contains(DirectConstArgContext::BLOCK)
&& let [stmt] = block.stmts.as_slice()
&& let StmtKind::Expr(expr) = &stmt.kind =>
{
self.can_lower_expr_to_const_arg_direct(expr, context)
}
(ExprKind::Lit(_), MacrolessMinGenericConstArgs) => Ok(()),
(ExprKind::Unary(UnOp::Neg, inner_expr), MacrolessMinGenericConstArgs)
if let ExprKind::Lit(_) = &inner_expr.kind =>
ExprKind::Lit(_) if context.contains(DirectConstArgContext::LIT) => Ok(()),
ExprKind::Unary(UnOp::Neg, inner_expr)
if context.contains(DirectConstArgContext::LIT)
&& let ExprKind::Lit(_) = &inner_expr.kind =>
{
Ok(())
}
(ExprKind::ConstBlock(_), MacrolessMinGenericConstArgs) => Ok(()),
(ExprKind::GcaMacro(_), MacrolessMinGenericConstArgs | MinGenericConstArgs) => {
ExprKind::ConstBlock(_) if context.contains(DirectConstArgContext::CONST_BLOCK) => {
Ok(())
}
ExprKind::GcaMacro(_) if context.contains(DirectConstArgContext::GCA_MACRO) => {
// Always report this as able to be represented directly. If it turns out not to be,
// `lower_expr_to_const_arg_direct` will report an error.
Ok(())
Expand Down Expand Up @@ -2927,11 +2942,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `can_lower_expr_to_const_arg_direct` always returns success upon encountering a
// ExprKind::GcaMacro, which effectively forces the expression to be lowered as a
// direct arg. If it actually turns out to not be possible, emit an error instead.
// Always use MacrolessMinGenericConstArgs, even if we're under regular GCA, because
// that's what the macro means: to enter a context that is like macroless GCA.
match self.can_lower_expr_to_const_arg_direct(
expr,
DirectConstArgContext::MacrolessMinGenericConstArgs,
self.direct_const_arg_context_enabled_by_gca_macro(),
) {
Ok(()) => self.lower_expr_to_const_arg_direct(expr, id_override),
Err(err) => err.emit(self),
Expand Down Expand Up @@ -3273,19 +3286,53 @@ impl<'hir> GenericArgsCtor<'hir> {
}
}

#[derive(Copy, Clone, Debug)]
enum DirectConstArgContext {
bitflags::bitflags! {
#[derive(Copy, Clone, Debug)]
struct DirectConstArgContext: u16 {
const TUPLE_CALL = 1 << 0;
const TUPLE = 1 << 1;
const PATH_PLAIN_PARAM = 1 << 2;
const PATH_CONST_CTOR = 1 << 3;
const PATH_ANY = 1 << 4;
const STRUCT = 1 << 5;
const ARRAY = 1 << 6;
const UNDERSCORE = 1 << 7;
const PAREN = 1 << 8;
const BLOCK = 1 << 9;
const LIT = 1 << 10;
const CONST_BLOCK = 1 << 11;
const GCA_MACRO = 1 << 12;
}
}

impl DirectConstArgContext {
/// The only allowed direct const arg representation is simple paths that nameres to generic
/// const parameters.
Stable,
const STABLE: DirectConstArgContext = Self::PATH_PLAIN_PARAM;

/// The allowed representations are what is allowed on stable, plus the `gca!` macro.
MinGenericConstArgs,
/// Expressions attempt to be lowered directly, and if that fails, the expression falls back to
/// being represented as an anon const.
const GCA: DirectConstArgContext = Self::STABLE.union(Self::GCA_MACRO);

/// These expressions are allowed inside the `gca!` macro, regardless of what feature is
/// enabling the base `gca!` functionality.
///
/// This context is also used under MinGenericConstArgs inside a `gca!` macro, for
/// simplicity, as they allow the same code.
MacrolessMinGenericConstArgs,
/// These are also allowed under macroless features without a `gca!` macro.
const GCA_BASE_FEATURES: DirectConstArgContext = Self::GCA
.union(DirectConstArgContext::UNDERSCORE)
.union(DirectConstArgContext::PAREN)
.union(DirectConstArgContext::BLOCK)
.union(DirectConstArgContext::LIT)
.union(DirectConstArgContext::CONST_BLOCK);

/// These are allowed under `#![feature(gca_min_const_items)]`
const GCA_MIN_CONST_ITEMS: DirectConstArgContext = DirectConstArgContext::PATH_ANY;

/// These are allowed under `#![feature(gca_adts)]`
const GCA_ADTS: DirectConstArgContext = DirectConstArgContext::PATH_CONST_CTOR
.union(DirectConstArgContext::TUPLE_CALL)
.union(DirectConstArgContext::TUPLE)
.union(DirectConstArgContext::STRUCT)
.union(DirectConstArgContext::ARRAY);
}

#[derive(Debug)]
Expand Down
59 changes: 40 additions & 19 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rustc_ast::{self as ast, AttrVec, GenericBound, NodeId, PatKind, attr, token
use rustc_attr_ir::{Attribute, AttributeKind};
use rustc_attr_parsing::AttributeParser;
use rustc_errors::msg;
use rustc_feature::Features;
use rustc_feature::{DependentFeature, Features};
use rustc_session::Session;
use rustc_session::diagnostics::{feature_err, feature_warn};
use rustc_span::{Span, Spanned, sym};
Expand Down Expand Up @@ -652,26 +652,47 @@ fn check_incompatible_features(sess: &Session, features: &Features) {
}

fn check_dependent_features(sess: &Session, features: &Features) {
for &(parent, children) in
rustc_feature::DEPENDENT_FEATURES.iter().filter(|(parent, _)| features.enabled(*parent))
for &(parent, ref children) in
rustc_feature::DEPENDENT_FEATURES.iter().filter(|(parent, children)| {
features.enabled(*parent) && !check_enabled(features, children)
})
{
if children.iter().any(|f| !features.enabled(*f)) {
let parent_span = features
.enabled_features_iter_stable_order()
.find_map(|(name, span)| (name == parent).then_some(span))
.unwrap();
// FIXME: should probably format this in fluent instead of here
let missing = children
let parent_span = features
.enabled_features_iter_stable_order()
.find_map(|(name, span)| (name == parent).then_some(span))
.unwrap();
// FIXME: should probably format this in fluent instead of here
let missing = format(features, &children);
sess.dcx().emit_err(diagnostics::MissingDependentFeatures { parent_span, parent, missing });
}

fn check_enabled(features: &Features, feature: &DependentFeature) -> bool {
match feature {
DependentFeature::And(children) => {
children.iter().all(|child| check_enabled(features, child))
}
DependentFeature::Or(children) => {
children.iter().any(|child| check_enabled(features, child))
}
DependentFeature::Leaf(symbol) => features.enabled(*symbol),
}
}

fn format(features: &Features, feature: &DependentFeature) -> String {
// FIXME: parentheses/precedence
match feature {
DependentFeature::And(children) => children
.iter()
.filter(|f| !features.enabled(**f))
.map(|s| format!("`{}`", s.as_str()))
.intersperse(String::from(", "))
.collect();
sess.dcx().emit_err(diagnostics::MissingDependentFeatures {
parent_span,
parent,
missing,
});
.filter(|child| !check_enabled(features, child))
.map(|child| format(features, child))
.intersperse(String::from(" and "))
.collect(),
DependentFeature::Or(children) => children
.iter()
.map(|child| format(features, child))
.intersperse(String::from(" or "))
.collect(),
DependentFeature::Leaf(symbol) => format!("`{}`", symbol.as_str()),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#![allow(rustc::potential_query_instability)]
#![cfg_attr(bootstrap, feature(allocator_api))]
#![cfg_attr(bootstrap, feature(never_type))]
#![cfg_attr(bootstrap, feature(unwrap_infallible))]
#![cfg_attr(not(bootstrap), feature(allocator_ext))]
#![cfg_attr(test, feature(test))]
#![deny(unsafe_op_in_unsafe_fn)]
Expand All @@ -35,7 +36,6 @@
#![feature(thread_id_value)]
#![feature(trusted_len)]
#![feature(type_alias_impl_trait)]
#![feature(unwrap_infallible)]
// tidy-alphabetical-end

// This allows derive macros to reference this crate
Expand Down
12 changes: 10 additions & 2 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,16 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
HandledOptions::HelpOnly(matches) => (matches, true),
};

let sopts = config::build_session_options(&mut default_early_dcx, &matches);
// fully initialize ice path static once unstable options are available as context
// For the purposes of checking that an --edition was passed, we ignore `-`.
let warn_unspecified_edition = match &matches.free[..] {
[] => false,
// We explicitly don't emit the note if we're consuming code from stdin. This can happen
// on some cargo invocations too.
[name] if name == "-" => false,
_ => true,
};
let sopts =
config::build_session_options(&mut default_early_dcx, &matches, warn_unspecified_edition);
let ice_file = ice_path_with_config(Some(&sopts.unstable_opts)).clone();

if let Some(ref code) = matches.opt_str("explain") {
Expand Down
Loading
Loading