Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
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 compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1849,7 +1849,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {

assert_eq!(tcx.trait_impl_of_assoc(def_id), None);
self.prove_clauses(
args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
args.terms().map(|t| ty::ClauseKind::WellFormed(t.into())),
locations,
ConstraintCategory::Boring,
);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1431,6 +1431,7 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>(
ty: Ty<'tcx>,
) -> SmallVec<Option<&'ll DIType>> {
if let ty::Adt(def, args) = *ty.kind() {
// FIXME: also do consts?
if args.types().next().is_some() {
let generics = cx.tcx.generics_of(def.did());
let names = get_parameter_names(cx, generics);
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ impl<'ll, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
generics: &ty::Generics,
args: GenericArgsRef<'tcx>,
) -> &'ll DIArray {
if args.types().next().is_none() {
if args.terms().next().is_none() {
return create_DIArray(DIB(cx), &[]);
}

Expand All @@ -293,6 +293,7 @@ impl<'ll, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
let names = get_parameter_names(cx, generics);
iter::zip(args, names)
.filter_map(|(kind, name)| {
// FIXME: debug info for consts (using `createTemplateValueParameter`?)
kind.as_type().map(|ty| {
let actual_type = cx.tcx.normalize_erasing_regions(
cx.typing_env(),
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_middle/src/ty/generic_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,11 @@ impl<'tcx> GenericArgs<'tcx> {
self.iter().filter_map(|k| k.as_const())
}

#[inline]
pub fn terms(&self) -> impl DoubleEndedIterator<Item = ty::Term<'tcx>> {
self.iter().filter_map(|k| k.as_term())
}

/// Returns generic arguments that are not lifetimes.
#[inline]
pub fn non_erasable_generics(&self) -> impl DoubleEndedIterator<Item = GenericArgKind<'tcx>> {
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2305,9 +2305,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
// `Foo<...>`.
if let Some(arg) = args.types().next() {
if let ty::Adt(_, arg_args) = arg.kind() {
if arg_args.consts().next().is_none()
&& arg_args.types().next().is_none()
{
if arg_args.terms().next().is_none() {
// Single param type with no type or const parameters:
// `Foo<Bar<'a>>`.
true
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_mir_transform/src/function_item_references.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
other_abi => format!("extern {other_abi} "),
};
let ident = self.tcx.item_ident(fn_id);
let ty_params = fn_args.types().map(|ty| format!("{ty}"));
let const_params = fn_args.consts().map(|c| format!("{c}"));
let params = ty_params.chain(const_params).join(", ");
let params = fn_args.terms().map(|term| format!("{term}")).join(", ");
let num_args = fn_sig.inputs().map_bound(|inputs| inputs.len()).skip_binder();
let variadic = if fn_sig.c_variadic() { ", ..." } else { "" };
let ret = if fn_sig.output().skip_binder().is_unit() { "" } else { " -> _" };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ impl<'tcx> InferSourceKind<'tcx> {
|| matches!(
ty.kind(),
ty::Adt(_, args)
if args.types().count() == 0 && args.consts().count() == 0
if args.terms().next().is_none()
)
{
// `ty` is either `_`, a primitive type like `u32` or a type with no type or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,12 +255,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// Pick the first generic parameter that still contains inference variables as the one
// we're going to emit an error for. If there are none (see above), fall back to
// a more general error.
let term = data
.trait_ref
.args
.iter()
.filter_map(ty::GenericArg::as_term)
.find(|s| s.has_non_region_infer());
let term = data.trait_ref.args.terms().find(|s| s.has_non_region_infer());

let mut err = if let Some(term) = term {
let candidates: Vec<_> = self
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
let new_args = new_trait.trait_ref.args;
let old_args = old_trait.trait_ref.args;

if !new_args.types().eq(old_args.types()) {
if !new_args.terms().eq(old_args.terms()) {
// We can't compare lifetimes if the types are different,
// so skip checking `old_clause`.
return true;
Expand Down Expand Up @@ -625,7 +625,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
}

fn is_param_no_infer(&self, args: GenericArgsRef<'tcx>) -> bool {
self.is_of_param(args.type_at(0)) && !args.types().any(|t| t.has_infer_types())
self.is_of_param(args.type_at(0)) && !args.terms().any(|t| t.has_infer_types())
}

pub fn is_of_param(&self, ty: Ty<'tcx>) -> bool {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// This suffices to allow chains like `FnMut` implemented in
// terms of `Fn` etc, but we could probably make this more
// precise still.
//
// FIXME(min_generic_const_args): Consider consts as well?
let unbound_input_types =
stack.fresh_trait_pred.skip_binder().trait_ref.args.types().any(|ty| ty.is_fresh());

Expand Down
5 changes: 3 additions & 2 deletions src/tools/clippy/clippy_lints/src/manual_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,9 @@ fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<
{
cx.typeck_results()
.node_args(count_func.hir_id)
.types()
.next()
.iter()
.next() // the `T` in `size_of::<T>`
.and_then(ty::GenericArg::as_type)
.map(|resolved_ty| (real_ty_span, resolved_ty))
} else {
None
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/methods/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl SelfKind {
} else if let ty::Adt(adt_def, args) = ty.kind()
&& matches!(cx.tcx.get_diagnostic_name(adt_def.did()), Some(sym::Rc | sym::Arc))
{
args.types().next() == Some(parent_ty)
args.iter().next().and_then(ty::GenericArg::as_type) == Some(parent_ty)
} else {
false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ enum RepeatKind {

fn get_ty_param(ty: Ty<'_>) -> Option<Ty<'_>> {
if let ty::Adt(_, subs) = ty.kind() {
subs.types().next()
subs.iter().next().and_then(ty::GenericArg::as_type)

@khyperia khyperia Aug 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could do subs.iter().next()?.as_type() in a few of these places, but whatever, that's a style choice, I don't care :P

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, why not :D? It does look cleaner.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I just now noticed that using types() is actually correct here.

it is also used on the Cow<'a, T> type, and the first parameter is the lifetime. That's why the filter_map is correct here and that this new change cause a ci job to fail.

} else {
None
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, iter: &hir::Expr
let collect_ret_ty = cx.typeck_results().expr_ty(expr);
if collect_ret_ty.is_diag_item(cx, sym::Result)
&& let ty::Adt(_, args) = collect_ret_ty.kind()
&& let Some(result_t) = args.types().next()
&& let Some(result_t) = args.iter().next().and_then(ty::GenericArg::as_type)
&& result_t.is_unit()
// get parts for snippet
{
Expand Down
4 changes: 3 additions & 1 deletion src/tools/clippy/clippy_lints/src/methods/ok_expect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
/// Given a `Result<T, E>` type, return its error type (`E`).
fn get_error_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option<Ty<'a>> {
match ty.kind() {
ty::Adt(adt, args) if cx.tcx.is_diagnostic_item(sym::Result, adt.did()) => args.types().nth(1),
ty::Adt(adt, args) if cx.tcx.is_diagnostic_item(sym::Result, adt.did()) => {
args.iter().nth(1).and_then(ty::GenericArg::as_type)
},
_ => None,
}
}
8 changes: 6 additions & 2 deletions src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, inverted:
Some(sym::mem_size_of | sym::mem_size_of_val)
)
{
cx.typeck_results().node_args(count_func.hir_id).types().next()
cx.typeck_results()
.node_args(count_func.hir_id)
.iter()
.next()
.and_then(ty::GenericArg::as_type)
} else {
None
}
Expand Down Expand Up @@ -92,7 +96,7 @@ fn get_pointee_ty_and_count_expr<'tcx>(
))

// Get the pointee type
&& let Some(pointee_ty) = cx.typeck_results().node_args(func.hir_id).types().next()
&& let Some(pointee_ty) = cx.typeck_results().node_args(func.hir_id).iter().next().and_then(ty::GenericArg::as_type)
{
return Some((pointee_ty, count));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,16 @@ fn is_size_pair(ty: Ty<'_>) -> bool {
}

fn same_except_params<'tcx>(subs1: GenericArgsRef<'tcx>, subs2: GenericArgsRef<'tcx>) -> bool {
// TODO: check const parameters as well. Currently this will consider `Array<5>` the same as
// `Array<6>`
for (ty1, ty2) in subs1.types().zip(subs2.types()).filter(|(ty1, ty2)| ty1 != ty2) {
match (ty1.kind(), ty2.kind()) {
(ty::Param(_), _) | (_, ty::Param(_)) => (),
(ty::Adt(adt1, subs1), ty::Adt(adt2, subs2)) if adt1 == adt2 && same_except_params(subs1, subs2) => (),
for (t1, t2) in subs1.terms().zip(subs2.terms()).filter(|(t1, t2)| t1 != t2) {
match (t1.kind(), t2.kind()) {
(ty::TermKind::Ty(ty1), ty::TermKind::Ty(ty2)) => match (ty1.kind(), ty2.kind()) {
(ty::Param(_), _) | (_, ty::Param(_)) => (),
(ty::Adt(adt1, subs1), ty::Adt(adt2, subs2)) if adt1 == adt2 && same_except_params(subs1, subs2) => (),
_ => return false,
},
// FIXME: check const parameters better as well. Is it still possible to treat equal
// consts as unequal?
(ty::TermKind::Const(c1), ty::TermKind::Const(c2)) if c1 == c2 => return true,
_ => return false,
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/tools/clippy/clippy_lints/src/useless_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
&& let b = cx.typeck_results().expr_ty(recv)
&& a.is_diag_item(cx, sym::Result)
&& let ty::Adt(_, args) = a.kind()
&& let Some(a_type) = args.types().next()
&& let Some(a_type) = args.iter().next().and_then(GenericArg::as_type)
&& same_type_modulo_regions(a_type, b)
{
span_lint_and_help(
Expand All @@ -424,7 +424,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
if name == sym::try_from_fn
&& a.is_diag_item(cx, sym::Result)
&& let ty::Adt(_, args) = a.kind()
&& let Some(a_type) = args.types().next()
&& let Some(a_type) = args.iter().next().and_then(GenericArg::as_type)
&& same_type_modulo_regions(a_type, b)
{
let hint = format!("consider removing `{}()`", snippet(cx, path.span, "TryFrom::try_from"));
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/lint/function-item-references.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ unsafe extern "C" fn variadic(_x: u32, _args: ...) { }
fn take_generic_ref<'a, T>(_x: &'a T) { }
fn take_generic_array<T, const N: usize>(_x: [T; N]) { }
fn multiple_generic<T, U>(_x: T, _y: U) { }
fn multiple_generic_arrays<T, U, const N: usize, const M: usize>(_x: [T; N], _y: [U; M]) { }
fn multiple_generic_arrays<T, const N: usize, U, const M: usize>(_x: [T; N], _y: [U; M]) { }
Comment thread
LorrensP-2158466 marked this conversation as resolved.

//function references passed to these functions should never lint
fn call_fn(f: &dyn Fn(u32) -> u32, x: u32) { f(x); }
Expand Down Expand Up @@ -120,7 +120,7 @@ fn main() {
//~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &multiple_generic::<u32, f32>);
//~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &multiple_generic_arrays::<u32, f32, 4, 8>);
println!("{:p}", &multiple_generic_arrays::<u32, 4, f32, 8>);
//~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &std::env::var::<String>);
//~^ WARNING taking a reference to a function item does not give a function pointer
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/lint/function-item-references.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ LL | println!("{:p}", &multiple_generic::<u32, f32>);
warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:123:22
|
LL | println!("{:p}", &multiple_generic_arrays::<u32, f32, 4, 8>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `multiple_generic_arrays` to obtain a function pointer: `multiple_generic_arrays::<u32, f32, 4, 8> as fn(_, _)`
LL | println!("{:p}", &multiple_generic_arrays::<u32, 4, f32, 8>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `multiple_generic_arrays` to obtain a function pointer: `multiple_generic_arrays::<u32, 4, f32, 8> as fn(_, _)`

warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:125:22
Expand Down
Loading