desc { "evaluating trait selection obligation `{}`", goal.value }
}
+ /// Evaluates whether the given type implements the given trait
+ /// in the given environment.
+ ///
+ /// The inputs are:
+ ///
+ /// - the def-id of the trait
+ /// - the self type
+ /// - the *other* type parameters of the trait, excluding the self-type
+ /// - the parameter environment
+ ///
+ /// FIXME. If the type, trait, or environment has inference variables,
+ /// this yields `EvaluatedToUnknown`. It should be refactored
+ /// to use canonicalization, really.
query type_implements_trait(
key: (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>, )
- ) -> bool {
+ ) -> traits::EvaluationResult {
desc { "evaluating `type_implements_trait` `{:?}`", key }
}
}
/// Check whether a `ty` implements given trait(trait_def_id).
-///
-/// NOTE: Always return `false` for a type which needs inference.
+/// See query definition for details.
fn type_implements_trait<'tcx>(
tcx: TyCtxt<'tcx>,
key: (
SubstsRef<'tcx>,
ParamEnv<'tcx>,
),
-) -> bool {
+) -> EvaluationResult {
let (trait_def_id, ty, params, param_env) = key;
debug!(
let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, params) };
+ // FIXME: If there are inference variables anywhere, just give up and assume
+ // we don't know the answer. This works around the ICEs that would result from
+ // using those inference variables within the `infer_ctxt` we create below.
+ // Really we should be using canonicalized variables, or perhaps removing
+ // this query altogether.
+ if (trait_ref, param_env).needs_infer() {
+ return EvaluationResult::EvaluatedToUnknown;
+ }
+
let obligation = Obligation {
cause: ObligationCause::dummy(),
param_env,
recursion_depth: 0,
predicate: trait_ref.without_const().to_predicate(tcx),
};
- tcx.infer_ctxt().enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation))
+ tcx.infer_ctxt().enter(|infcx| infcx.evaluate_obligation_no_overflow(&obligation))
}
pub fn provide(providers: &mut ty::query::Providers) {
return false;
}
let ty_params = cx.tcx.mk_substs(ty_params.iter());
- cx.tcx.type_implements_trait((trait_id, ty, ty_params, cx.param_env))
+ cx.tcx
+ .type_implements_trait((trait_id, ty, ty_params, cx.param_env))
+ .must_apply_modulo_regions()
}
/// Checks whether this type implements `Drop`.
match ty.kind() {
ty::Adt(adt, _) => must_use_attr(cx.tcx.get_attrs(adt.did)).is_some(),
ty::Foreign(ref did) => must_use_attr(cx.tcx.get_attrs(*did)).is_some(),
- ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => {
+ ty::Slice(ty)
+ | ty::Array(ty, _)
+ | ty::RawPtr(ty::TypeAndMut { ty, .. })
+ | ty::Ref(_, ty, _) => {
// for the Array case we don't need to care for the len == 0 case
// because we don't want to lint functions returning empty arrays
is_must_use_ty(cx, *ty)
- },
+ }
ty::Tuple(substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
ty::Opaque(ref 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::Trait(trait_predicate, _) = predicate.kind().skip_binder()
+ {
if must_use_attr(cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() {
return true;
}
}
}
false
- },
+ }
ty::Dynamic(binder, _) => {
for predicate in binder.iter() {
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
}
}
false
- },
+ }
_ => false,
}
}
// not succeed
/// Checks if `Ty` is normalizable. This function is useful
/// to avoid crashes on `layout_of`.
-pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
+pub fn is_normalizable<'tcx>(
+ cx: &LateContext<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ ty: Ty<'tcx>,
+) -> bool {
is_normalizable_helper(cx, param_env, ty, &mut FxHashMap::default())
}
if infcx.at(&cause, param_env).normalize(ty).is_ok() {
match ty.kind() {
ty::Adt(def, substs) => def.variants.iter().all(|variant| {
- variant
- .fields
- .iter()
- .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache))
+ variant.fields.iter().all(|field| {
+ is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache)
+ })
}),
_ => ty.walk().all(|generic_arg| match generic_arg.unpack() {
GenericArgKind::Type(inner_ty) if inner_ty != ty => {
is_normalizable_helper(cx, param_env, inner_ty, cache)
- },
+ }
_ => true, // if inner_ty == ty, we've already checked it
}),
}
match ty.kind() {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true,
ty::Ref(_, inner, _) if *inner.kind() == ty::Str => true,
- ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(inner_type),
+ ty::Array(inner_type, _) | ty::Slice(inner_type) => {
+ is_recursively_primitive_type(inner_type)
+ }
ty::Tuple(inner_types) => inner_types.types().all(is_recursively_primitive_type),
_ => false,
}
/// removed.
pub fn peel_mid_ty_refs(ty: Ty<'_>) -> (Ty<'_>, usize) {
fn peel(ty: Ty<'_>, count: usize) -> (Ty<'_>, usize) {
- if let ty::Ref(_, ty, _) = ty.kind() {
- peel(ty, count + 1)
- } else {
- (ty, count)
- }
+ if let ty::Ref(_, ty, _) = ty.kind() { peel(ty, count + 1) } else { (ty, count) }
}
peel(ty, 0)
}
return false;
}
- substs_a
- .iter()
- .zip(substs_b.iter())
- .all(|(arg_a, arg_b)| match (arg_a.unpack(), arg_b.unpack()) {
- (GenericArgKind::Const(inner_a), GenericArgKind::Const(inner_b)) => inner_a == inner_b,
+ substs_a.iter().zip(substs_b.iter()).all(|(arg_a, arg_b)| {
+ match (arg_a.unpack(), arg_b.unpack()) {
+ (GenericArgKind::Const(inner_a), GenericArgKind::Const(inner_b)) => {
+ inner_a == inner_b
+ }
(GenericArgKind::Type(type_a), GenericArgKind::Type(type_b)) => {
same_type_and_consts(type_a, type_b)
- },
+ }
_ => true,
- })
- },
+ }
+ })
+ }
_ => a == b,
}
}