about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-09-09 18:14:23 +0000
committerbors <bors@rust-lang.org>2025-09-09 18:14:23 +0000
commit7ad23f43a225546c095123de52cc07d8719f8e2b (patch)
tree0e99435039bfbf29f791983825ed7062bc785f77 /compiler
parent364da5d88d772fa40fb20353443595385443ac25 (diff)
parenta40ec4c50a0a0475123675c3f4202eaf5cbedb77 (diff)
downloadrust-7ad23f43a225546c095123de52cc07d8719f8e2b.tar.gz
rust-7ad23f43a225546c095123de52cc07d8719f8e2b.zip
Auto merge of #146375 - matthiaskrgr:rollup-utik9zj, r=matthiaskrgr
Rollup of 6 pull requests

Successful merges:

 - rust-lang/rust#145463 (Reject invalid literal suffixes in tuple indexing, tuple struct indexing, and struct field name position)
 - rust-lang/rust#145929 (fix APITIT being treated as a normal generic parameter in suggestions)
 - rust-lang/rust#146001 (Update getopts to remove unicode-width dependency)
 - rust-lang/rust#146365 (triagebot: warn about #[rustc_intrinsic_const_stable_indirect])
 - rust-lang/rust#146366 (add approx_delta to all gamma tests)
 - rust-lang/rust#146373 (fix comments about trait solver cycle heads)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs73
-rw-r--r--compiler/rustc_parse/messages.ftl3
-rw-r--r--compiler/rustc_parse/src/errors.rs4
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs26
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs5
-rw-r--r--compiler/rustc_type_ir/src/search_graph/mod.rs4
-rw-r--r--compiler/rustc_type_ir/src/search_graph/stack.rs4
7 files changed, 60 insertions, 59 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index b5c0ca4727c..63d0f400aef 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -85,7 +85,9 @@ use rustc_infer::traits::ObligationCause;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::print::with_types_for_signature;
-use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypingMode};
+use rustc_middle::ty::{
+    self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypingMode,
+};
 use rustc_middle::{bug, span_bug};
 use rustc_session::parse::feature_err;
 use rustc_span::def_id::CRATE_DEF_ID;
@@ -233,8 +235,7 @@ fn missing_items_err(
     };
 
     // Obtain the level of indentation ending in `sugg_sp`.
-    let padding =
-        tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
+    let padding = tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(String::new);
     let (mut missing_trait_item, mut missing_trait_item_none, mut missing_trait_item_label) =
         (Vec::new(), Vec::new(), Vec::new());
 
@@ -331,6 +332,7 @@ fn default_body_is_unstable(
 fn bounds_from_generic_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     predicates: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
+    assoc: ty::AssocItem,
 ) -> (String, String) {
     let mut types: FxIndexMap<Ty<'tcx>, Vec<DefId>> = FxIndexMap::default();
     let mut projections = vec![];
@@ -354,34 +356,50 @@ fn bounds_from_generic_predicates<'tcx>(
     }
 
     let mut where_clauses = vec![];
-    let mut types_str = vec![];
-    for (ty, bounds) in types {
-        if let ty::Param(_) = ty.kind() {
-            let mut bounds_str = vec![];
-            for bound in bounds {
-                let mut projections_str = vec![];
-                for projection in &projections {
-                    let p = projection.skip_binder();
-                    if bound == tcx.parent(p.projection_term.def_id)
-                        && p.projection_term.self_ty() == ty
-                    {
-                        let name = tcx.item_name(p.projection_term.def_id);
-                        projections_str.push(format!("{} = {}", name, p.term));
+    let generics = tcx.generics_of(assoc.def_id);
+    let types_str = generics
+        .own_params
+        .iter()
+        .filter(|p| matches!(p.kind, GenericParamDefKind::Type { synthetic: false, .. }))
+        .map(|p| {
+            // we just checked that it's a type, so the unwrap can't fail
+            let ty = tcx.mk_param_from_def(p).as_type().unwrap();
+            if let Some(bounds) = types.get(&ty) {
+                let mut bounds_str = vec![];
+                for bound in bounds.iter().copied() {
+                    let mut projections_str = vec![];
+                    for projection in &projections {
+                        let p = projection.skip_binder();
+                        if bound == tcx.parent(p.projection_term.def_id)
+                            && p.projection_term.self_ty() == ty
+                        {
+                            let name = tcx.item_name(p.projection_term.def_id);
+                            projections_str.push(format!("{} = {}", name, p.term));
+                        }
+                    }
+                    let bound_def_path = tcx.def_path_str(bound);
+                    if projections_str.is_empty() {
+                        where_clauses.push(format!("{}: {}", ty, bound_def_path));
+                    } else {
+                        bounds_str.push(format!(
+                            "{}<{}>",
+                            bound_def_path,
+                            projections_str.join(", ")
+                        ));
                     }
                 }
-                let bound_def_path = tcx.def_path_str(bound);
-                if projections_str.is_empty() {
-                    where_clauses.push(format!("{}: {}", ty, bound_def_path));
+                if bounds_str.is_empty() {
+                    ty.to_string()
                 } else {
-                    bounds_str.push(format!("{}<{}>", bound_def_path, projections_str.join(", ")));
+                    format!("{}: {}", ty, bounds_str.join(" + "))
                 }
-            }
-            if bounds_str.is_empty() {
-                types_str.push(ty.to_string());
             } else {
-                types_str.push(format!("{}: {}", ty, bounds_str.join(" + ")));
+                ty.to_string()
             }
-        } else {
+        })
+        .collect::<Vec<_>>();
+    for (ty, bounds) in types.into_iter() {
+        if !matches!(ty.kind(), ty::Param(_)) {
             // Avoid suggesting the following:
             // fn foo<T, <T as Trait>::Bar>(_: T) where T: Trait, <T as Trait>::Bar: Other {}
             where_clauses.extend(
@@ -473,10 +491,10 @@ fn fn_sig_suggestion<'tcx>(
     let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() };
 
     let safety = sig.safety.prefix_str();
-    let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates);
+    let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates, assoc);
 
     // FIXME: this is not entirely correct, as the lifetimes from borrowed params will
-    // not be present in the `fn` definition, not will we account for renamed
+    // not be present in the `fn` definition, nor will we account for renamed
     // lifetimes between the `impl` and the `trait`, but this should be good enough to
     // fill in a significant portion of the missing code, and other subsequent
     // suggestions can help the user fix the code.
@@ -512,6 +530,7 @@ fn suggestion_signature<'tcx>(
             let (generics, where_clauses) = bounds_from_generic_predicates(
                 tcx,
                 tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args),
+                assoc,
             );
             format!("type {}{generics} = /* Type */{where_clauses};", assoc.name())
         }
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 77dd313d9b8..72cd75f6d89 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -479,9 +479,6 @@ parse_invalid_identifier_with_leading_number = identifiers cannot start with a n
 
 parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid
     .label = invalid suffix `{$suffix}`
-    .tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
-    .tuple_exception_line_2 = on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
-    .tuple_exception_line_3 = see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
 
 parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
     .note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 797d4830c2f..00ca5acd84d 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1017,10 +1017,6 @@ pub(crate) struct InvalidLiteralSuffixOnTupleIndex {
     #[label]
     pub span: Span,
     pub suffix: Symbol,
-    #[help(parse_tuple_exception_line_1)]
-    #[help(parse_tuple_exception_line_2)]
-    #[help(parse_tuple_exception_line_3)]
-    pub exception: bool,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 4c02547357e..81a5d48d94e 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1163,7 +1163,10 @@ impl<'a> Parser<'a> {
                         suffix,
                     }) => {
                         if let Some(suffix) = suffix {
-                            self.expect_no_tuple_index_suffix(current.span, suffix);
+                            self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
+                                span: current.span,
+                                suffix,
+                            });
                         }
                         match self.break_up_float(symbol, current.span) {
                             // 1e2
@@ -1239,7 +1242,8 @@ impl<'a> Parser<'a> {
         suffix: Option<Symbol>,
     ) -> Box<Expr> {
         if let Some(suffix) = suffix {
-            self.expect_no_tuple_index_suffix(ident_span, suffix);
+            self.dcx()
+                .emit_err(errors::InvalidLiteralSuffixOnTupleIndex { span: ident_span, suffix });
         }
         self.mk_expr(lo.to(ident_span), ExprKind::Field(base, Ident::new(field, ident_span)))
     }
@@ -2225,24 +2229,6 @@ impl<'a> Parser<'a> {
         })
     }
 
-    pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) {
-        if [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suffix) {
-            // #59553: warn instead of reject out of hand to allow the fix to percolate
-            // through the ecosystem when people fix their macros
-            self.dcx().emit_warn(errors::InvalidLiteralSuffixOnTupleIndex {
-                span,
-                suffix,
-                exception: true,
-            });
-        } else {
-            self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
-                span,
-                suffix,
-                exception: false,
-            });
-        }
-    }
-
     /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
     /// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
     pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, Box<Expr>> {
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 3bbca622975..ed4069dae93 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1335,7 +1335,10 @@ impl<'a> Parser<'a> {
         if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = self.token.kind
         {
             if let Some(suffix) = suffix {
-                self.expect_no_tuple_index_suffix(self.token.span, suffix);
+                self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
+                    span: self.token.span,
+                    suffix,
+                });
             }
             self.bump();
             Ok(Ident::new(symbol, self.prev_token.span))
diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs
index dbbc0c217d7..8f8f019510f 100644
--- a/compiler/rustc_type_ir/src/search_graph/mod.rs
+++ b/compiler/rustc_type_ir/src/search_graph/mod.rs
@@ -1262,7 +1262,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
             encountered_overflow |= stack_entry.encountered_overflow;
             debug_assert_eq!(stack_entry.input, input);
 
-            // If the current goal is not the root of a cycle, we are done.
+            // If the current goal is not a cycle head, we are done.
             //
             // There are no provisional cache entries which depend on this goal.
             let Some(usages) = stack_entry.usages else {
@@ -1278,7 +1278,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
             //
             // Check whether we reached a fixpoint, either because the final result
             // is equal to the provisional result of the previous iteration, or because
-            // this was only the root of either coinductive or inductive cycles, and the
+            // this was only the head of either coinductive or inductive cycles, and the
             // final result is equal to the initial response for that case.
             if self.reached_fixpoint(cx, &stack_entry, usages, result) {
                 self.rebase_provisional_cache_entries(&stack_entry, |_, result| result);
diff --git a/compiler/rustc_type_ir/src/search_graph/stack.rs b/compiler/rustc_type_ir/src/search_graph/stack.rs
index 3fd8e2bd16e..8348666be41 100644
--- a/compiler/rustc_type_ir/src/search_graph/stack.rs
+++ b/compiler/rustc_type_ir/src/search_graph/stack.rs
@@ -13,7 +13,7 @@ rustc_index::newtype_index! {
     pub(super) struct StackDepth {}
 }
 
-/// Stack entries of the evaluation stack. Its fields tend to be lazily
+/// Stack entries of the evaluation stack. Its fields tend to be lazily updated
 /// when popping a child goal or completely immutable.
 #[derive_where(Debug; X: Cx)]
 pub(super) struct StackEntry<X: Cx> {
@@ -42,7 +42,7 @@ pub(super) struct StackEntry<X: Cx> {
     /// Whether evaluating this goal encountered overflow. Lazily updated.
     pub encountered_overflow: bool,
 
-    /// Whether and how this goal has been used as the root of a cycle. Lazily updated.
+    /// Whether and how this goal has been used as a cycle head. Lazily updated.
     pub usages: Option<HeadUsages>,
 
     /// We want to be able to ignore head usages if they happen inside of candidates