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
aa7d812
remove `internal_impls_macro` feature
cyrgani Mar 17, 2026
e350a56
move features into the correct section
cyrgani Feb 24, 2026
c8a2c46
bootstrap: Optionally print a backtrace if a command fails
jyn514 Mar 16, 2026
45b22ef
tests: Activate must_not_suspend test for MutexGuard dropped before a…
Enselic Mar 18, 2026
bef4b47
Updates derive_where and removes workaround
spirali Mar 19, 2026
74776c4
Rewrite `query_ensure_result`.
nnethercote Mar 19, 2026
cec0a68
Resolve paths for `impl` restrictions using `smart_resolve_path`
CoCo-Japan-pan Mar 19, 2026
4a60dae
Add UI tests for path resolution errors of `impl` restrictions
CoCo-Japan-pan Mar 19, 2026
082cdf7
Preserve braces around `self` in use tree pretty printing
aytey Mar 19, 2026
c777685
Fix whitespace after fragment specifiers in macro pretty printing
aytey Mar 19, 2026
e9740a4
Insert space after float literal ending with `.` in pretty printer
aytey Mar 19, 2026
3fd11aa
Rollup merge of #153556 - CoCo-Japan-pan:impl-restriction-lowering, r…
JonathanBrouwer Mar 19, 2026
a22dc5f
Rollup merge of #153992 - ferrocene:jyn/bootstrap-backtrace, r=jieyou…
JonathanBrouwer Mar 19, 2026
65c7618
Rollup merge of #154019 - cyrgani:feature-clean, r=joboet
JonathanBrouwer Mar 19, 2026
fd52c57
Rollup merge of #154059 - Enselic:dropped-mutex-guard, r=Kivooeo
JonathanBrouwer Mar 19, 2026
8d8ce5f
Rollup merge of #154075 - nnethercote:rewrite-query_ensure_result, r=…
JonathanBrouwer Mar 19, 2026
91fcef7
Rollup merge of #154082 - spirali:fix-derive-where, r=lqd
JonathanBrouwer Mar 19, 2026
22859b2
Rollup merge of #154084 - aytey:fix-use-self-braces, r=Kivooeo
JonathanBrouwer Mar 19, 2026
68fca67
Rollup merge of #154086 - aytey:fix-float-range-spacing, r=Kivooeo
JonathanBrouwer Mar 19, 2026
6f3b14a
Rollup merge of #154087 - aytey:fix-fragment-specifier-whitespace, r=…
JonathanBrouwer Mar 19, 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
4 changes: 2 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1140,9 +1140,9 @@ version = "0.1.96"

[[package]]
name = "derive-where"
version = "1.6.0"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f"
checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534"
dependencies = [
"proc-macro2",
"quote",
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,19 @@ fn print_crate_inner<'a>(
/// - #63896: `#[allow(unused,` must be printed rather than `#[allow(unused ,`
/// - #73345: `#[allow(unused)]` must be printed rather than `# [allow(unused)]`
///
/// Returns `true` if both token trees are identifier-like tokens that would
/// merge into a single token if printed without a space between them.
/// E.g. `ident` + `where` would merge into `identwhere`.
fn idents_would_merge(tt1: &TokenTree, tt2: &TokenTree) -> bool {
fn is_ident_like(tt: &TokenTree) -> bool {
matches!(
tt,
TokenTree::Token(Token { kind: token::Ident(..) | token::NtIdent(..), .. }, _,)
)
}
is_ident_like(tt1) && is_ident_like(tt2)
}

fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool {
use Delimiter::*;
use TokenTree::{Delimited as Del, Token as Tok};
Expand Down Expand Up @@ -794,6 +807,13 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
if let Some(next) = iter.peek() {
if spacing == Spacing::Alone && space_between(tt, next) {
self.space();
} else if spacing != Spacing::Alone && idents_would_merge(tt, next) {
// When tokens from macro `tt` captures preserve their
// original `Joint`/`JointHidden` spacing, adjacent
// identifier-like tokens can be concatenated without a
// space (e.g. `$x:identwhere`). Insert a space to
// prevent this.
self.space();
}
}
}
Expand Down
48 changes: 37 additions & 11 deletions compiler/rustc_ast_pretty/src/pprust/state/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,15 @@ impl<'a> State<'a> {
//
// loop { break x; }.method();
//
self.print_expr_cond_paren(
receiver,
receiver.precedence() < ExprPrecedence::Unambiguous,
fixup.leftmost_subexpression_with_dot(),
);
let needs_paren = receiver.precedence() < ExprPrecedence::Unambiguous;
self.print_expr_cond_paren(receiver, needs_paren, fixup.leftmost_subexpression_with_dot());

// If the receiver is an unsuffixed float literal like `0.`, insert
// a space so the `.` of the method call doesn't merge with the
// trailing dot: `0. .method()` instead of `0..method()`.
if !needs_paren && expr_ends_with_dot(receiver) {
self.word(" ");
}
self.word(".");
self.print_ident(segment.ident);
if let Some(args) = &segment.args {
Expand Down Expand Up @@ -658,11 +661,15 @@ impl<'a> State<'a> {
);
}
ast::ExprKind::Field(expr, ident) => {
let needs_paren = expr.precedence() < ExprPrecedence::Unambiguous;
self.print_expr_cond_paren(
expr,
expr.precedence() < ExprPrecedence::Unambiguous,
needs_paren,
fixup.leftmost_subexpression_with_dot(),
);
if !needs_paren && expr_ends_with_dot(expr) {
self.word(" ");
}
self.word(".");
self.print_ident(*ident);
}
Expand All @@ -685,11 +692,15 @@ impl<'a> State<'a> {
let fake_prec = ExprPrecedence::LOr;
if let Some(e) = start {
let start_fixup = fixup.leftmost_subexpression_with_operator(true);
self.print_expr_cond_paren(
e,
start_fixup.precedence(e) < fake_prec,
start_fixup,
);
let needs_paren = start_fixup.precedence(e) < fake_prec;
self.print_expr_cond_paren(e, needs_paren, start_fixup);
// If the start expression is a float literal ending with
// `.`, we need a space before `..` or `..=` so that the
// dots don't merge. E.g. `0. ..45.` must not become
// `0...45.`.
if !needs_paren && expr_ends_with_dot(e) {
self.word(" ");
}
}
match limits {
ast::RangeLimits::HalfOpen => self.word(".."),
Expand Down Expand Up @@ -1025,3 +1036,18 @@ fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String
template.push('"');
template
}

/// Returns `true` if the printed representation of this expression ends with
/// a `.` character — specifically, an unsuffixed float literal like `0.` or
/// `45.`. This is used to insert whitespace before range operators (`..`,
/// `..=`) so that the dots don't merge (e.g. `0. ..45.` instead of `0...45.`).
fn expr_ends_with_dot(expr: &ast::Expr) -> bool {
match &expr.kind {
ast::ExprKind::Lit(token_lit) => {
token_lit.kind == token::Float
&& token_lit.suffix.is_none()
&& token_lit.symbol.as_str().ends_with('.')
}
_ => false,
}
}
8 changes: 7 additions & 1 deletion compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,13 @@ impl<'a> State<'a> {
}
if items.is_empty() {
self.word("{}");
} else if let [(item, _)] = items.as_slice() {
} else if let [(item, _)] = items.as_slice()
&& !item
.prefix
.segments
.first()
.is_some_and(|seg| seg.ident.name == rustc_span::symbol::kw::SelfLower)
{
self.print_use_tree(item);
} else {
let cb = self.cbox(INDENT_UNIT);
Expand Down
43 changes: 27 additions & 16 deletions compiler/rustc_middle/src/query/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,23 +77,34 @@ where
C: QueryCache<Value = Erased<Result<T, ErrorGuaranteed>>>,
Result<T, ErrorGuaranteed>: Erasable,
{
let convert = |value: Erased<Result<T, ErrorGuaranteed>>| -> Result<(), ErrorGuaranteed> {
match erase::restore_val(value) {
Ok(_) => Ok(()),
Err(guar) => Err(guar),
}
};

match try_get_cached(tcx, &query.cache, key) {
Some(value) => erase::restore_val(value).map(drop),
None => (query.execute_query_fn)(
tcx,
DUMMY_SP,
key,
QueryMode::Ensure { ensure_mode: EnsureMode::Ok },
)
.map(erase::restore_val)
.map(|value| value.map(drop))
// Either we actually executed the query, which means we got a full `Result`,
// or we can just assume the query succeeded, because it was green in the
// incremental cache. If it is green, that means that the previous compilation
// that wrote to the incremental cache compiles successfully. That is only
// possible if the cache entry was `Ok(())`, so we emit that here, without
// actually encoding the `Result` in the cache or loading it from there.
.unwrap_or(Ok(())),
Some(value) => convert(value),
None => {
match (query.execute_query_fn)(
tcx,
DUMMY_SP,
key,
QueryMode::Ensure { ensure_mode: EnsureMode::Ok },
) {
// We executed the query. Convert the successful result.
Some(res) => convert(res),

// Reaching here means we didn't execute the query, but we can just assume the
// query succeeded, because it was green in the incremental cache. If it is green,
// that means that the previous compilation that wrote to the incremental cache
// compiles successfully. That is only possible if the cache entry was `Ok(())`, so
// we emit that here, without actually encoding the `Result` in the cache or
// loading it from there.
None => Ok(()),
}
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_resolve/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,10 @@ pub(crate) struct ExpectedModuleFound {
#[diag("cannot determine resolution for the visibility", code = E0578)]
pub(crate) struct Indeterminate(#[primary_span] pub(crate) Span);

#[derive(Diagnostic)]
#[diag("trait implementation can only be restricted to ancestor modules")]
pub(crate) struct RestrictionAncestorOnly(#[primary_span] pub(crate) Span);

#[derive(Diagnostic)]
#[diag("cannot use a tool module through an import")]
pub(crate) struct ToolModuleImported {
Expand Down
43 changes: 39 additions & 4 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,8 @@ pub(crate) enum PathSource<'a, 'ast, 'ra> {
DefineOpaques,
/// Resolving a macro
Macro,
/// Paths for module or crate root. Used for restrictions.
Module,
}

impl PathSource<'_, '_, '_> {
Expand All @@ -460,7 +462,8 @@ impl PathSource<'_, '_, '_> {
PathSource::Type
| PathSource::Trait(_)
| PathSource::Struct(_)
| PathSource::DefineOpaques => TypeNS,
| PathSource::DefineOpaques
| PathSource::Module => TypeNS,
PathSource::Expr(..)
| PathSource::Pat
| PathSource::TupleStruct(..)
Expand All @@ -485,7 +488,8 @@ impl PathSource<'_, '_, '_> {
| PathSource::DefineOpaques
| PathSource::Delegation
| PathSource::PreciseCapturingArg(..)
| PathSource::Macro => false,
| PathSource::Macro
| PathSource::Module => false,
}
}

Expand Down Expand Up @@ -528,6 +532,7 @@ impl PathSource<'_, '_, '_> {
PathSource::ReturnTypeNotation | PathSource::Delegation => "function",
PathSource::PreciseCapturingArg(..) => "type or const parameter",
PathSource::Macro => "macro",
PathSource::Module => "module",
}
}

Expand Down Expand Up @@ -626,6 +631,7 @@ impl PathSource<'_, '_, '_> {
),
PathSource::PreciseCapturingArg(MacroNS) => false,
PathSource::Macro => matches!(res, Res::Def(DefKind::Macro(_), _)),
PathSource::Module => matches!(res, Res::Def(DefKind::Mod, _)),
}
}

Expand All @@ -646,6 +652,12 @@ impl PathSource<'_, '_, '_> {
(PathSource::PreciseCapturingArg(..), true) => E0799,
(PathSource::PreciseCapturingArg(..), false) => E0800,
(PathSource::Macro, _) => E0425,
// FIXME: There is no dedicated error code for this case yet.
// E0577 already covers the same situation for visibilities,
// so we reuse it here for now. It may make sense to generalize
// it for restrictions in the future.
(PathSource::Module, true) => E0577,
(PathSource::Module, false) => E0433,
}
}
}
Expand Down Expand Up @@ -2174,7 +2186,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
| PathSource::Type
| PathSource::PreciseCapturingArg(..)
| PathSource::ReturnTypeNotation
| PathSource::Macro => false,
| PathSource::Macro
| PathSource::Module => false,
PathSource::Expr(..)
| PathSource::Pat
| PathSource::Struct(_)
Expand Down Expand Up @@ -2800,7 +2813,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
self.diag_metadata.current_impl_items = None;
}

ItemKind::Trait(box Trait { generics, bounds, items, .. }) => {
ItemKind::Trait(box Trait { generics, bounds, items, impl_restriction, .. }) => {
// resolve paths for `impl` restrictions
self.resolve_impl_restriction_path(impl_restriction);

// Create a new rib for the trait-wide type parameters.
self.with_generic_param_rib(
&generics.params,
Expand Down Expand Up @@ -4389,6 +4405,25 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}
}

fn resolve_impl_restriction_path(&mut self, restriction: &'ast ast::ImplRestriction) {
match &restriction.kind {
ast::RestrictionKind::Unrestricted => (),
ast::RestrictionKind::Restricted { path, id, shorthand: _ } => {
self.smart_resolve_path(*id, &None, path, PathSource::Module);
if let Some(res) = self.r.partial_res_map[&id].full_res()
&& let Some(def_id) = res.opt_def_id()
{
if !self.r.is_accessible_from(
Visibility::Restricted(def_id),
self.parent_scope.module,
) {
self.r.dcx().create_err(errors::RestrictionAncestorOnly(path.span)).emit();
}
}
}
}
}

// High-level and context dependent path resolution routine.
// Resolves the path and records the resolution into definition map.
// If resolution fails tries several techniques to find likely
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_type_ir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ edition = "2024"
# tidy-alphabetical-start
arrayvec = { version = "0.7", default-features = false }
bitflags = "2.4.1"
derive-where = "1.2.7"
derive-where = "1.6.1"
ena = "0.14.4"
indexmap = "2.0.0"
rustc-hash = "2.0.0"
Expand Down
20 changes: 3 additions & 17 deletions compiler/rustc_type_ir/src/binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,7 @@ use crate::{self as ty, DebruijnIndex, Interner, UniverseIndex};
/// for more details.
///
/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
// FIXME(derive-where#136): Need to use separate `derive_where` for
// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd`
// impls from incorrectly relying on `T: Copy` and `T: Ord`.
#[derive_where(Copy; I: Interner, T: Copy)]
#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, T)]
#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner, T)]
#[derive(GenericTypeVisitable)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub struct Binder<I: Interner, T> {
Expand Down Expand Up @@ -365,12 +361,7 @@ impl<I: Interner> TypeVisitor<I> for ValidateBoundVars<I> {
/// `instantiate`.
///
/// See <https://rustc-dev-guide.rust-lang.org/ty_module/early_binder.html> for more details.
// FIXME(derive-where#136): Need to use separate `derive_where` for
// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd`
// impls from incorrectly relying on `T: Copy` and `T: Ord`.
#[derive_where(Ord; I: Interner, T: Ord)]
#[derive_where(Copy; I: Interner, T: Copy)]
#[derive_where(Clone, PartialOrd, PartialEq, Hash, Debug; I: Interner, T)]
#[derive_where(Clone, Copy, PartialOrd, Ord, PartialEq, Hash, Debug; I: Interner, T)]
#[derive(GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
Expand Down Expand Up @@ -964,12 +955,7 @@ pub enum BoundVarIndexKind {
/// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are
/// identified by both a universe, as well as a name residing within that universe. Distinct bound
/// regions/types/consts within the same universe simply have an unknown relationship to one
// FIXME(derive-where#136): Need to use separate `derive_where` for
// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd`
// impls from incorrectly relying on `T: Copy` and `T: Ord`.
#[derive_where(Ord; I: Interner, T: Ord)]
#[derive_where(Copy; I: Interner, T: Copy)]
#[derive_where(Clone, PartialOrd, PartialEq, Eq, Hash; I: Interner, T)]
#[derive_where(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash; I: Interner, T)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(
feature = "nightly",
Expand Down
3 changes: 1 addition & 2 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@
#![feature(core_intrinsics)]
#![feature(coverage_attribute)]
#![feature(disjoint_bitor)]
#![feature(internal_impls_macro)]
#![feature(link_cfg)]
#![feature(offset_of_enum)]
#![feature(panic_internals)]
#![feature(pattern_type_macro)]
Expand Down Expand Up @@ -144,6 +142,7 @@
#![feature(intra_doc_pointers)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(link_cfg)]
#![feature(link_llvm_intrinsics)]
#![feature(macro_metavar_expr)]
#![feature(macro_metavar_expr_concat)]
Expand Down
3 changes: 0 additions & 3 deletions library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ use crate::pin::UnsafePinned;
/// u32,
/// }
/// ```
#[unstable(feature = "internal_impls_macro", issue = "none")]
// Allow implementations of `UnsizedConstParamTy` even though std cannot use that feature.
#[allow_internal_unstable(const_param_ty_trait)]
macro marker_impls {
( $(#[$($meta:tt)*])* $Trait:ident for $({$($bounds:tt)*})? $T:ty $(, $($rest:tt)*)? ) => {
$(#[$($meta)*])* impl< $($($bounds)*)? > $Trait for $T {}
Expand Down
Loading
Loading