use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety};
-use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{
+ type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
+ TyCtxtInferExt,
+};
use rustc_lint::LateContext;
use rustc_middle::mir::interpret::{ConstValue, Scalar};
use rustc_middle::ty::{
- self, AdtDef, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, GenericParamDefKind, IntTy, List, ParamEnv,
- Predicate, PredicateKind, ProjectionTy, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable,
- TypeVisitable, TypeVisitor, UintTy, VariantDef, VariantDiscr,
+ self, AdtDef, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate, PredicateKind,
+ ProjectionTy, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
+ VariantDef, VariantDiscr,
};
use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{sym, Span, Symbol, DUMMY_SP};
use rustc_target::abi::{Size, VariantIdx};
use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use std::iter;
use crate::{match_def_path, path_res, paths};
match predicate.kind().skip_binder() {
// For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
// and check substituions to find `U`.
- ty::PredicateKind::Trait(trait_predicate) => {
+ ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => {
if trait_predicate
.trait_ref
.substs
},
// For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
// so we check the term for `U`.
- ty::PredicateKind::Projection(projection_predicate) => {
+ ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate)) => {
if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
if contains_ty_adt_constructor_opaque(cx, ty, needle) {
return true;
pub fn get_iterator_item_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
cx.tcx
.get_diagnostic_item(sym::Iterator)
- .and_then(|iter_did| get_associated_type(cx, ty, iter_did, "Item"))
-}
-
-/// Returns the associated type `name` for `ty` as an implementation of `trait_id`.
-/// Do not invoke without first verifying that the type implements the trait.
-pub fn get_associated_type<'tcx>(
- cx: &LateContext<'tcx>,
- ty: Ty<'tcx>,
- trait_id: DefId,
- name: &str,
-) -> Option<Ty<'tcx>> {
- cx.tcx
- .associated_items(trait_id)
- .find_by_name_and_kind(cx.tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
- .and_then(|assoc| {
- let proj = cx.tcx.mk_projection(assoc.def_id, cx.tcx.mk_substs_trait(ty, &[]));
- cx.tcx.try_normalize_erasing_regions(cx.param_env, proj).ok()
- })
+ .and_then(|iter_did| cx.get_associated_type(ty, iter_did, "Item"))
}
/// Get the diagnostic name of a type, e.g. `sym::HashMap`. To check if a type
trait_id: DefId,
ty_params: &[GenericArg<'tcx>],
) -> bool {
- implements_trait_with_env(cx.tcx, cx.param_env, ty, trait_id, ty_params)
+ implements_trait_with_env(
+ cx.tcx,
+ cx.param_env,
+ ty,
+ trait_id,
+ ty_params.iter().map(|&arg| Some(arg)),
+ )
}
/// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
param_env: ParamEnv<'tcx>,
ty: Ty<'tcx>,
trait_id: DefId,
- ty_params: &[GenericArg<'tcx>],
+ ty_params: impl IntoIterator<Item = Option<GenericArg<'tcx>>>,
) -> bool {
// Clippy shouldn't have infer types
assert!(!ty.needs_infer());
if ty.has_escaping_bound_vars() {
return false;
}
- let ty_params = tcx.mk_substs(ty_params.iter());
let infcx = tcx.infer_ctxt().build();
+ let orig = TypeVariableOrigin {
+ kind: TypeVariableOriginKind::MiscVariable,
+ span: DUMMY_SP,
+ };
+ let ty_params = tcx.mk_substs(
+ ty_params
+ .into_iter()
+ .map(|arg| arg.unwrap_or_else(|| infcx.next_ty_var(orig).into())),
+ );
infcx
- .type_implements_trait(trait_id, ty, ty_params, param_env)
+ .type_implements_trait(trait_id, [ty.into()].into_iter().chain(ty_params), param_env)
.must_apply_modulo_regions()
}
ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
ty::Opaque(def_id, _) => {
for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
- if let ty::PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder() {
+ if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() {
if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
return true;
}
cache.insert(ty, false);
let infcx = cx.tcx.infer_ctxt().build();
let cause = rustc_middle::traits::ObligationCause::dummy();
- let result = if infcx.at(&cause, param_env).normalize(ty).is_ok() {
+ let result = if infcx.at(&cause, param_env).query_normalize(ty).is_ok() {
match ty.kind() {
ty::Adt(def, substs) => def.variants().iter().all(|variant| {
variant
for pred in predicates {
match pred.kind().skip_binder() {
- PredicateKind::Trait(p)
+ PredicateKind::Clause(ty::Clause::Trait(p))
if (lang_items.fn_trait() == Some(p.def_id())
|| lang_items.fn_mut_trait() == Some(p.def_id())
|| lang_items.fn_once_trait() == Some(p.def_id()))
}
inputs = Some(i);
},
- PredicateKind::Projection(p)
+ PredicateKind::Clause(ty::Clause::Projection(p))
if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output()
&& p.projection_ty.self_ty() == ty =>
{
.subst_iter_copied(cx.tcx, ty.substs)
{
match pred.kind().skip_binder() {
- PredicateKind::Trait(p)
+ PredicateKind::Clause(ty::Clause::Trait(p))
if (lang_items.fn_trait() == Some(p.def_id())
|| lang_items.fn_mut_trait() == Some(p.def_id())
|| lang_items.fn_once_trait() == Some(p.def_id())) =>
}
inputs = Some(i);
},
- PredicateKind::Projection(p) if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() => {
+ PredicateKind::Clause(ty::Clause::Projection(p))
+ if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() =>
+ {
if output.is_some() {
// Multiple different fn trait impls. Is this even allowed?
return None;
predicates
.iter()
.try_fold(false, |found, p| {
- if let PredicateKind::Trait(p) = p.kind().skip_binder()
+ if let PredicateKind::Clause(ty::Clause::Trait(p)) = p.kind().skip_binder()
&& let ty::Param(self_ty) = p.trait_ref.self_ty().kind()
&& ty.index == self_ty.index
{
the given arguments are: `{substs:#?}`",
assoc_item.def_id,
substs.len(),
- params.map(GenericParamDefKind::descr).collect::<Vec<_>>(),
+ params.map(ty::GenericParamDefKind::descr).collect::<Vec<_>>(),
);
if let Some((idx, (param, arg))) = params
.find(|(_, (param, arg))| {
!matches!(
(param, arg),
- (GenericParamDefKind::Lifetime, GenericArgKind::Lifetime(_))
- | (GenericParamDefKind::Type { .. }, GenericArgKind::Type(_))
- | (GenericParamDefKind::Const { .. }, GenericArgKind::Const(_))
+ (ty::GenericParamDefKind::Lifetime, GenericArgKind::Lifetime(_))
+ | (ty::GenericParamDefKind::Type { .. }, GenericArgKind::Type(_))
+ | (ty::GenericParamDefKind::Const { .. }, GenericArgKind::Const(_))
)
})
{
note: the expected parameters are {:#?}\n\
the given arguments are {substs:#?}",
param.descr(),
- params.map(GenericParamDefKind::descr).collect::<Vec<_>>()
+ params.map(ty::GenericParamDefKind::descr).collect::<Vec<_>>()
);
}
}