Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5dfe784
diagnostics: print HRTB binders before fn qualifiers
qaijuang May 1, 2026
89005b2
Update `askama` version to `0.16.0`
GuillaumeGomez May 4, 2026
08aca77
Regen `proc_macro_dep`
GuillaumeGomez May 4, 2026
cf636ec
resolve: Factor out reporting of "cannot reexport" errors into a sepa…
petrochenkov Apr 30, 2026
65e5bd6
resolve: Catch "cannot reexport" errors from macros 2.0 better
petrochenkov Apr 30, 2026
21c58d8
resolve: Harden some invariant checks for visibilities
petrochenkov Apr 30, 2026
fadb747
rust-analyzer: Fix `pub_use_of_private_extern_crate` lint
petrochenkov May 4, 2026
45b9459
Update `askama` version to `0.16.0` in `clippy`
GuillaumeGomez May 4, 2026
c89c812
generic_const_args: allow paths to non type consts
khyperia May 4, 2026
664177f
Remove const closure hacks in libstd
oli-obk Apr 27, 2026
a015eb1
Revert const hack and use const closure
oli-obk Apr 28, 2026
23cea55
Remove duplicate debug assert
zetanumbers May 5, 2026
ee35020
Revert "remove `MethodReceiverExpr` special-casing"
cyrgani May 5, 2026
82708d8
Rollup merge of #155341 - khyperia:non-type-const, r=BoxyUwU
GuillaumeGomez May 5, 2026
cb43cd6
Rollup merge of #156014 - petrochenkov:kvak, r=mu001999
GuillaumeGomez May 5, 2026
186a72f
Rollup merge of #156058 - qaijuang:issue-151393, r=JohnTitor
GuillaumeGomez May 5, 2026
a3df747
Rollup merge of #156184 - cyrgani:macros-are-weird, r=petrochenkov
GuillaumeGomez May 5, 2026
783aba6
Rollup merge of #155957 - oli-obk:const-closure-std, r=jhpratt
GuillaumeGomez May 5, 2026
226a8fd
Rollup merge of #156127 - GuillaumeGomez:update-askama, r=Urgau
GuillaumeGomez May 5, 2026
d6dc695
Rollup merge of #156183 - zetanumbers:rm_duplicate_dbg_ass, r=mati865
GuillaumeGomez May 5, 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
24 changes: 14 additions & 10 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"

[[package]]
name = "askama"
version = "0.15.4"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08e1676b346cadfec169374f949d7490fd80a24193d37d2afce0c047cf695e57"
checksum = "f1bf825125edd887a019d0a3a837dcc5499a68b0d034cc3eb594070c3e18addc"
dependencies = [
"askama_macros",
"itoa",
Expand All @@ -187,12 +187,13 @@ dependencies = [

[[package]]
name = "askama_derive"
version = "0.15.4"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7661ff56517787343f376f75db037426facd7c8d3049cef8911f1e75016f3a37"
checksum = "e1c7065972a130eafa84215f21352ae15b4a7393da48c1f5e103904490736738"
dependencies = [
"askama_parser",
"basic-toml",
"glob",
"memchr",
"proc-macro2",
"quote",
Expand All @@ -204,24 +205,24 @@ dependencies = [

[[package]]
name = "askama_macros"
version = "0.15.4"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "713ee4dbfd1eb719c2dab859465b01fa1d21cb566684614a713a6b7a99a4e47b"
checksum = "0e23b1d2c4bd39a41971f6124cef4cc6fd0540913ecb90919b69ab3bbe44ae1a"
dependencies = [
"askama_derive",
]

[[package]]
name = "askama_parser"
version = "0.15.4"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d62d674238a526418b30c0def480d5beadb9d8964e7f38d635b03bf639c704c"
checksum = "7db09fde9143e7ac4513358fb32ee32847125b63b18ea715afd487956da715da"
dependencies = [
"rustc-hash 2.1.1",
"serde",
"serde_derive",
"unicode-ident",
"winnow 0.7.13",
"winnow 1.0.0",
]

[[package]]
Expand Down Expand Up @@ -756,7 +757,7 @@ checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681"
dependencies = [
"serde",
"termcolor",
"unicode-width 0.1.14",
"unicode-width 0.2.2",
]

[[package]]
Expand Down Expand Up @@ -6625,6 +6626,9 @@ name = "winnow"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8"
dependencies = [
"memchr",
]

[[package]]
name = "winsplit"
Expand Down
23 changes: 23 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
check_incompatible_features(sess, features);
check_dependent_features(sess, features);
check_new_solver_banned_features(sess, features);
check_features_requiring_new_solver(sess, features);

let mut visitor = PostExpansionVisitor { sess, features };

Expand Down Expand Up @@ -739,3 +740,25 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) {
});
}
}

fn check_features_requiring_new_solver(sess: &Session, features: &Features) {
if sess.opts.unstable_opts.next_solver.globally {
return;
}

// Require the new solver with GCA, because the old solver can't implement GCA correctly as it
// does not support normalization obligations for free and inherent consts.
if let Some(gca_span) = features
.enabled_lang_features()
.iter()
.find(|feat| feat.gate_name == sym::generic_const_args)
.map(|feat| feat.attr_sp)
{
#[allow(rustc::symbol_intern_string_literal)]
sess.dcx().emit_err(errors::MissingDependentFeatures {
parent_span: gca_span,
parent: sym::generic_const_args,
missing: String::from("-Znext-solver=globally"),
});
}
}
4 changes: 0 additions & 4 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,10 +423,6 @@ pub trait MacResult {
None
}

fn make_method_receiver_expr(self: Box<Self>) -> Option<Box<ast::Expr>> {
self.make_expr()
}

/// Creates zero or more items.
fn make_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
None
Expand Down
19 changes: 14 additions & 5 deletions compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,23 @@ macro_rules! ast_fragments {
/// Can also serve as an input and intermediate result for macro expansion operations.
pub enum AstFragment {
OptExpr(Option<Box<ast::Expr>>),
MethodReceiverExpr(Box<ast::Expr>),
$($Kind($AstTy),)*
}

/// "Discriminant" of an AST fragment.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum AstFragmentKind {
OptExpr,
MethodReceiverExpr,
$($Kind,)*
}

impl AstFragmentKind {
pub fn name(self) -> &'static str {
match self {
AstFragmentKind::OptExpr => "expression",
AstFragmentKind::MethodReceiverExpr => "expression",
$(AstFragmentKind::$Kind => $kind_name,)*
}
}
Expand All @@ -90,6 +93,8 @@ macro_rules! ast_fragments {
match self {
AstFragmentKind::OptExpr =>
result.make_expr().map(Some).map(AstFragment::OptExpr),
AstFragmentKind::MethodReceiverExpr =>
result.make_expr().map(AstFragment::MethodReceiverExpr),
$(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
}
}
Expand All @@ -116,6 +121,13 @@ macro_rules! ast_fragments {
}
}

pub(crate) fn make_method_receiver_expr(self) -> Box<ast::Expr> {
match self {
AstFragment::MethodReceiverExpr(expr) => expr,
_ => panic!("AstFragment::make_method_receiver_expr called on the wrong kind of fragment"),
}
}

$(pub fn $make_ast(self) -> $AstTy {
match self {
AstFragment::$Kind(ast) => ast,
Expand All @@ -134,6 +146,7 @@ macro_rules! ast_fragments {
*opt_expr = vis.filter_map_expr(expr)
}
}
AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr),
$($(AstFragment::$Kind(ast) => vis.$visit_ast(ast),)?)*
$($(AstFragment::$Kind(ast) =>
ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast, $($args)*)),)?)*
Expand All @@ -144,6 +157,7 @@ macro_rules! ast_fragments {
match self {
AstFragment::OptExpr(Some(expr)) => try_visit!(visitor.visit_expr(expr)),
AstFragment::OptExpr(None) => {}
AstFragment::MethodReceiverExpr(expr) => try_visit!(visitor.visit_method_receiver_expr(expr)),
$($(AstFragment::$Kind(ast) => try_visit!(visitor.$visit_ast(ast)),)?)*
$($(AstFragment::$Kind(ast) => walk_list!(visitor, $visit_ast_elt, &ast[..], $($args)*),)?)*
}
Expand All @@ -166,11 +180,6 @@ ast_fragments! {
one fn visit_expr;
fn make_expr;
}
MethodReceiverExpr(Box<ast::Expr>) {
"expression";
one fn visit_method_receiver_expr;
fn make_method_receiver_expr;
}
Pat(Box<ast::Pat>) {
"pattern";
one fn visit_pat;
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3064,7 +3064,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
span: Span,
) -> Result<(), ErrorGuaranteed> {
let tcx = self.tcx();
if tcx.is_type_const(def_id) {
// FIXME(gca): Intentionally disallowing paths to inherent associated non-type constants
// until a refactoring for how generic args for IACs are represented has been landed.
let is_inherent_assoc_const = tcx.def_kind(def_id)
== DefKind::AssocConst { is_type_const: false }
&& tcx.def_kind(tcx.parent(def_id)) == DefKind::Impl { of_trait: false };
if tcx.is_type_const(def_id)
|| tcx.features().generic_const_args() && !is_inherent_assoc_const
{
Ok(())
} else {
let mut err = self.dcx().struct_span_err(
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ impl<'tcx> rustc_type_ir::inherent::Features<TyCtxt<'tcx>> for &'tcx rustc_featu
self.generic_const_exprs()
}

fn generic_const_args(self) -> bool {
self.generic_const_args()
}

fn coroutine_clone(self) -> bool {
self.coroutine_clone()
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_middle/src/ty/context/impl_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
self.type_of_opaque_hir_typeck(def_id)
}
fn is_type_const(self, def_id: DefId) -> bool {
self.is_type_const(def_id)
}
fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
self.const_of_item(def_id)
}
Expand Down
38 changes: 38 additions & 0 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,44 @@ where
self.delegate.evaluate_const(param_env, uv)
}

pub(super) fn evaluate_const_and_instantiate_normalizes_to_term(
&mut self,
goal: Goal<I, ty::NormalizesTo<I>>,
uv: ty::UnevaluatedConst<I>,
) -> QueryResult<I> {
match self.evaluate_const(goal.param_env, uv) {
Some(evaluated) => {
self.instantiate_normalizes_to_term(goal, evaluated.into());
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
None if self.cx().features().generic_const_args() => {
// HACK(khyperia): calling `resolve_vars_if_possible` here shouldn't be necessary,
// `try_evaluate_const` calls `resolve_vars_if_possible` already. However, we want
// to check `has_non_region_infer` against the type with vars resolved (i.e. check
// if there are vars we failed to resolve), so we need to call it again here.
// Perhaps we could split EvaluateConstErr::HasGenericsOrInfers into HasGenerics and
// HasInfers or something, make evaluate_const return that, and make this branch be
// based on that, rather than checking `has_non_region_infer`.
if self.resolve_vars_if_possible(uv).has_non_region_infer() {
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
} else {
// We do not instantiate to the `uv` passed in, but rather
// `goal.predicate.alias`. The `uv` passed in might correspond to the `impl`
// form of a constant (with generic arguments corresponding to the impl block),
// however, we want to structurally instantiate to the original, non-rebased,
// trait `Self` form of the constant (with generic arguments being the trait
// `Self` type).
self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
}
None => {
// Legacy behavior: always treat as ambiguous
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
}
}

pub(super) fn is_transmutable(
&mut self,
src: I::Ty,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use rustc_type_ir::{self as ty, Interner};
use tracing::instrument;

use crate::delegate::SolverDelegate;
use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult};
use crate::solve::{EvalCtxt, Goal, QueryResult};

impl<D, I> EvalCtxt<'_, D>
where
Expand All @@ -14,17 +14,7 @@ where
&mut self,
goal: Goal<I, ty::NormalizesTo<I>>,
) -> QueryResult<I> {
if let Some(normalized_const) = self.evaluate_const(
goal.param_env,
ty::UnevaluatedConst::new(
goal.predicate.alias.def_id().try_into().unwrap(),
goal.predicate.alias.args,
),
) {
self.instantiate_normalizes_to_term(goal, normalized_const.into());
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} else {
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
let uv = goal.predicate.alias.expect_ct(self.cx());
self.evaluate_const_and_instantiate_normalizes_to_term(goal, uv)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,20 @@ where
.map(|pred| goal.with(cx, pred)),
);

let actual = if free_alias.kind(cx).is_type() {
cx.type_of(free_alias.def_id()).instantiate(cx, free_alias.args).skip_norm_wip().into()
} else {
cx.const_of_item(free_alias.def_id())
.instantiate(cx, free_alias.args)
.skip_norm_wip()
.into()
let actual = match free_alias.kind(cx) {
ty::AliasTermKind::FreeTy { def_id } => {
cx.type_of(def_id).instantiate(cx, free_alias.args).skip_norm_wip().into()
}
ty::AliasTermKind::FreeConst { def_id } if cx.is_type_const(def_id) => {
cx.const_of_item(def_id).instantiate(cx, free_alias.args).skip_norm_wip().into()
}
ty::AliasTermKind::FreeConst { .. } => {
return self.evaluate_const_and_instantiate_normalizes_to_term(
goal,
free_alias.expect_ct(cx),
);
}
kind => panic!("expected free alias, found {kind:?}"),
};

self.instantiate_normalizes_to_term(goal, actual);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,23 @@ where
.map(|pred| goal.with(cx, pred)),
);

let normalized = if inherent.kind(cx).is_type() {
cx.type_of(inherent.def_id()).instantiate(cx, inherent_args).skip_norm_wip().into()
} else {
cx.const_of_item(inherent.def_id())
.instantiate(cx, inherent_args)
.skip_norm_wip()
.into()
let normalized = match inherent.kind(cx) {
ty::AliasTermKind::InherentTy { def_id } => {
cx.type_of(def_id).instantiate(cx, inherent_args).skip_norm_wip().into()
}
ty::AliasTermKind::InherentConst { def_id } if cx.is_type_const(def_id) => {
cx.const_of_item(def_id).instantiate(cx, inherent_args).skip_norm_wip().into()
}
ty::AliasTermKind::InherentConst { .. } => {
// FIXME(gca): This is dead code at the moment. It should eventually call
// self.evaluate_const like projected consts do in consider_impl_candidate in
// normalizes_to/mod.rs. However, how generic args are represented for IACs is up in
// the air right now.
// Will self.evaluate_const eventually take the inherent_args or the impl_args form
// of args? It might be either.
panic!("References to inherent associated consts should have been blocked");
}
kind => panic!("expected inherent alias, found {kind:?}"),
};
self.instantiate_normalizes_to_term(goal, normalized);
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
Expand Down
Loading
Loading