diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 14b1c9b31ef9f..c858eb200d791 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1850,7 +1850,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, ); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 33f6eca6be9cc..54bdfb5f442d9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1432,6 +1432,7 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>( ty: Ty<'tcx>, ) -> SmallVec> { 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); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index d6d9946450899..4267d61ad4445 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -289,7 +289,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), &[]); } @@ -298,6 +298,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(), diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index a9ca6bfef5534..fceb737dc8365 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -518,6 +518,11 @@ impl<'tcx> GenericArgs<'tcx> { self.iter().filter_map(|k| k.as_const()) } + #[inline] + pub fn terms(&self) -> impl DoubleEndedIterator> { + self.iter().filter_map(|k| k.as_term()) + } + /// Returns generic arguments that are not lifetimes. #[inline] pub fn non_erasable_generics(&self) -> impl DoubleEndedIterator> { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 4ab474fd89fe6..f52d096d53e35 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -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>`. true diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 41d16c00ff64b..a7b27f824e9e2 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -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 { " -> _" }; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 1a66ddb8e2238..903c3998fd4b6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -678,7 +678,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 diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 06d882a309489..c450d02d58cd6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -182,17 +182,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// share an inference variable into a single diagnostic. pub(super) fn ambiguity_term(&self, predicate: ty::Predicate<'tcx>) -> Option> { match predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => data - .trait_ref - .args - .iter() - .filter_map(ty::GenericArg::as_term) - .find(|term| term.has_non_region_infer()), + ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { + data.trait_ref.args.terms().find(|term| term.has_non_region_infer()) + } ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => data .projection_term .args - .iter() - .filter_map(ty::GenericArg::as_term) + .terms() .chain([data.term]) .find(|term| term.has_non_region_infer()), ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => Some(term), diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index c885406f6dcfb..8cfc86880a5e3 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -454,7 +454,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; @@ -624,7 +624,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 { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9b4ee13bf1b63..4eae79cd41c16 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1216,6 +1216,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()); diff --git a/src/tools/clippy/clippy_lints/src/manual_bits.rs b/src/tools/clippy/clippy_lints/src/manual_bits.rs index da0d9be1cb7fa..92313eab318d2 100644 --- a/src/tools/clippy/clippy_lints/src/manual_bits.rs +++ b/src/tools/clippy/clippy_lints/src/manual_bits.rs @@ -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::` + .and_then(ty::GenericArg::as_type) .map(|resolved_ty| (real_ty_span, resolved_ty)) } else { None diff --git a/src/tools/clippy/clippy_lints/src/methods/lib.rs b/src/tools/clippy/clippy_lints/src/methods/lib.rs index 84038283bcf8f..9246ed331ee94 100644 --- a/src/tools/clippy/clippy_lints/src/methods/lib.rs +++ b/src/tools/clippy/clippy_lints/src/methods/lib.rs @@ -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 } diff --git a/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs b/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs index 6f556fe592af8..155f31d6528cf 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs @@ -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 { diff --git a/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs b/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs index 4982506036ef6..182757f347d8c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs @@ -37,7 +37,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr /// Given a `Result` type, return its error type (`E`). fn get_error_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option> { 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)?.as_type(), _ => None, } } diff --git a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs index 3623039aece15..98e84f38bbaea 100644 --- a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs +++ b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs @@ -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 } diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 05f4071406477..83eca20266684 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -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. Currently this will consider `Array<5>` the same as + // `Array<6>` + (ty::TermKind::Const(_), ty::TermKind::Const(_)) => {}, _ => return false, } } diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index ed9bf1e86e691..2df9269524ab2 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -400,7 +400,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( @@ -425,7 +425,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")); diff --git a/tests/ui/lint/function-item-references.rs b/tests/ui/lint/function-item-references.rs index 5afd8341473f3..739e5fab8a35e 100644 --- a/tests/ui/lint/function-item-references.rs +++ b/tests/ui/lint/function-item-references.rs @@ -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(_x: [T; N]) { } fn multiple_generic(_x: T, _y: U) { } -fn multiple_generic_arrays(_x: [T; N], _y: [U; M]) { } +fn multiple_generic_arrays(_x: [T; N], _y: [U; M]) { } //function references passed to these functions should never lint fn call_fn(f: &dyn Fn(u32) -> u32, x: u32) { f(x); } @@ -120,7 +120,7 @@ fn main() { //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &multiple_generic::); //~^ WARNING taking a reference to a function item does not give a function pointer - println!("{:p}", &multiple_generic_arrays::); + println!("{:p}", &multiple_generic_arrays::); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &std::env::var::); //~^ WARNING taking a reference to a function item does not give a function pointer diff --git a/tests/ui/lint/function-item-references.stderr b/tests/ui/lint/function-item-references.stderr index 837a4b2087fdf..f2c7a03fc8f70 100644 --- a/tests/ui/lint/function-item-references.stderr +++ b/tests/ui/lint/function-item-references.stderr @@ -127,8 +127,8 @@ LL | println!("{:p}", &multiple_generic::); 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::); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `multiple_generic_arrays` to obtain a function pointer: `multiple_generic_arrays:: as fn(_, _)` +LL | println!("{:p}", &multiple_generic_arrays::); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `multiple_generic_arrays` to obtain a function pointer: `multiple_generic_arrays:: as fn(_, _)` warning: taking a reference to a function item does not give a function pointer --> $DIR/function-item-references.rs:125:22