/// Same as above, but for a function pointer type with the given signature.
FnPointer(ImplSourceFnPointerData<'tcx, N>),
- /// ImplSource for a builtin `DeterminantKind` trait implementation.
- DiscriminantKind(ImplSourceDiscriminantKindData),
-
- /// ImplSource for a builtin `Pointee` trait implementation.
- Pointee(ImplSourcePointeeData),
-
/// ImplSource automatically generated for a generator.
Generator(ImplSourceGeneratorData<'tcx, N>),
ImplSource::Future(c) => c.nested,
ImplSource::Object(d) => d.nested,
ImplSource::FnPointer(d) => d.nested,
- ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
- | ImplSource::Pointee(ImplSourcePointeeData) => vec![],
ImplSource::TraitAlias(d) => d.nested,
ImplSource::TraitUpcasting(d) => d.nested,
ImplSource::ConstDestruct(i) => i.nested,
ImplSource::Future(c) => &c.nested,
ImplSource::Object(d) => &d.nested,
ImplSource::FnPointer(d) => &d.nested,
- ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
- | ImplSource::Pointee(ImplSourcePointeeData) => &[],
ImplSource::TraitAlias(d) => &d.nested,
ImplSource::TraitUpcasting(d) => &d.nested,
ImplSource::ConstDestruct(i) => &i.nested,
fn_ty: p.fn_ty,
nested: p.nested.into_iter().map(f).collect(),
}),
- ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) => {
- ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
- }
- ImplSource::Pointee(ImplSourcePointeeData) => {
- ImplSource::Pointee(ImplSourcePointeeData)
- }
ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData {
alias_def_id: d.alias_def_id,
substs: d.substs,
pub nested: Vec<N>,
}
-// FIXME(@lcnr): This should be refactored and merged with other builtin vtables.
-#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
-pub struct ImplSourceDiscriminantKindData;
-
-#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
-pub struct ImplSourcePointeeData;
-
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ImplSourceConstDestructData<N> {
use super::SelectionContext;
use super::SelectionError;
use super::{
- ImplSourceClosureData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData,
- ImplSourceFutureData, ImplSourceGeneratorData, ImplSourcePointeeData,
+ ImplSourceClosureData, ImplSourceFnPointerData, ImplSourceFutureData, ImplSourceGeneratorData,
ImplSourceUserDefinedData,
};
use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
+use rustc_infer::traits::ImplSourceBuiltinData;
use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable};
}
}
}
- super::ImplSource::DiscriminantKind(..) => {
- // While `DiscriminantKind` is automatically implemented for every type,
- // the concrete discriminant may not be known yet.
- //
- // Any type with multiple potential discriminant types is therefore not eligible.
+ super::ImplSource::Builtin(..) => {
+ // While a builtin impl may be known to exist, the associated type may not yet
+ // be known. Any type with multiple potential associated types is therefore
+ // not eligible.
let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty());
- match self_ty.kind() {
- ty::Bool
- | ty::Char
- | ty::Int(_)
- | ty::Uint(_)
- | ty::Float(_)
- | ty::Adt(..)
- | ty::Foreign(_)
- | ty::Str
- | ty::Array(..)
- | ty::Slice(_)
- | ty::RawPtr(..)
- | ty::Ref(..)
- | ty::FnDef(..)
- | ty::FnPtr(..)
- | ty::Dynamic(..)
- | ty::Closure(..)
- | ty::Generator(..)
- | ty::GeneratorWitness(..)
- | ty::Never
- | ty::Tuple(..)
- // Integers and floats always have `u8` as their discriminant.
- | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
-
- ty::Projection(..)
- | ty::Opaque(..)
- | ty::Param(..)
- | ty::Bound(..)
- | ty::Placeholder(..)
- | ty::Infer(..)
- | ty::Error(_) => false,
- }
- }
- super::ImplSource::Pointee(..) => {
- // While `Pointee` is automatically implemented for every type,
- // the concrete metadata type may not be known yet.
- //
- // Any type with multiple potential metadata types is therefore not eligible.
- let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty());
-
- let tail = selcx.tcx().struct_tail_with_normalize(
- self_ty,
- |ty| {
- // We throw away any obligations we get from this, since we normalize
- // and confirm these obligations once again during confirmation
- normalize_with_depth(
- selcx,
- obligation.param_env,
- obligation.cause.clone(),
- obligation.recursion_depth + 1,
- ty,
- )
- .value
- },
- || {},
- );
-
- match tail.kind() {
- ty::Bool
- | ty::Char
- | ty::Int(_)
- | ty::Uint(_)
- | ty::Float(_)
- | ty::Str
- | ty::Array(..)
- | ty::Slice(_)
- | ty::RawPtr(..)
- | ty::Ref(..)
- | ty::FnDef(..)
- | ty::FnPtr(..)
- | ty::Dynamic(..)
- | ty::Closure(..)
- | ty::Generator(..)
- | ty::GeneratorWitness(..)
- | ty::Never
- // Extern types have unit metadata, according to RFC 2850
- | ty::Foreign(_)
- // If returned by `struct_tail_without_normalization` this is a unit struct
- // without any fields, or not a struct, and therefore is Sized.
- | ty::Adt(..)
- // If returned by `struct_tail_without_normalization` this is the empty tuple.
- | ty::Tuple(..)
- // Integers and floats are always Sized, and so have unit type metadata.
- | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
-
- // type parameters, opaques, and unnormalized projections have pointer
- // metadata if they're known (e.g. by the param_env) to be sized
- ty::Param(_) | ty::Projection(..) | ty::Opaque(..)
- if selcx.infcx().predicate_must_hold_modulo_regions(
- &obligation.with(
- selcx.tcx(),
- ty::Binder::dummy(selcx.tcx().at(obligation.cause.span).mk_trait_ref(
- LangItem::Sized,
- [self_ty],
- ))
- .without_const(),
- ),
- ) =>
- {
- true
+ let lang_items = selcx.tcx().lang_items();
+ if lang_items.discriminant_kind_trait() == Some(poly_trait_ref.def_id()) {
+ match self_ty.kind() {
+ ty::Bool
+ | ty::Char
+ | ty::Int(_)
+ | ty::Uint(_)
+ | ty::Float(_)
+ | ty::Adt(..)
+ | ty::Foreign(_)
+ | ty::Str
+ | ty::Array(..)
+ | ty::Slice(_)
+ | ty::RawPtr(..)
+ | ty::Ref(..)
+ | ty::FnDef(..)
+ | ty::FnPtr(..)
+ | ty::Dynamic(..)
+ | ty::Closure(..)
+ | ty::Generator(..)
+ | ty::GeneratorWitness(..)
+ | ty::Never
+ | ty::Tuple(..)
+ // Integers and floats always have `u8` as their discriminant.
+ | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
+
+ // type parameters, opaques, and unnormalized projections have pointer
+ // metadata if they're known (e.g. by the param_env) to be sized
+ ty::Param(_)
+ | ty::Projection(..)
+ | ty::Opaque(..)
+ | ty::Bound(..)
+ | ty::Placeholder(..)
+ | ty::Infer(..)
+ | ty::Error(_) => false,
}
+ } else if lang_items.pointee_trait() == Some(poly_trait_ref.def_id()) {
+ let tail = selcx.tcx().struct_tail_with_normalize(
+ self_ty,
+ |ty| {
+ // We throw away any obligations we get from this, since we normalize
+ // and confirm these obligations once again during confirmation
+ normalize_with_depth(
+ selcx,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ ty,
+ )
+ .value
+ },
+ || {},
+ );
- // FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
- ty::Param(_)
- | ty::Projection(..)
- | ty::Opaque(..)
- | ty::Bound(..)
- | ty::Placeholder(..)
- | ty::Infer(..)
- | ty::Error(_) => {
- if tail.has_infer_types() {
- candidate_set.mark_ambiguous();
+ match tail.kind() {
+ ty::Bool
+ | ty::Char
+ | ty::Int(_)
+ | ty::Uint(_)
+ | ty::Float(_)
+ | ty::Str
+ | ty::Array(..)
+ | ty::Slice(_)
+ | ty::RawPtr(..)
+ | ty::Ref(..)
+ | ty::FnDef(..)
+ | ty::FnPtr(..)
+ | ty::Dynamic(..)
+ | ty::Closure(..)
+ | ty::Generator(..)
+ | ty::GeneratorWitness(..)
+ | ty::Never
+ // Extern types have unit metadata, according to RFC 2850
+ | ty::Foreign(_)
+ // If returned by `struct_tail_without_normalization` this is a unit struct
+ // without any fields, or not a struct, and therefore is Sized.
+ | ty::Adt(..)
+ // If returned by `struct_tail_without_normalization` this is the empty tuple.
+ | ty::Tuple(..)
+ // Integers and floats are always Sized, and so have unit type metadata.
+ | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
+
+ // type parameters, opaques, and unnormalized projections have pointer
+ // metadata if they're known (e.g. by the param_env) to be sized
+ ty::Param(_) | ty::Projection(..) | ty::Opaque(..)
+ if selcx.infcx().predicate_must_hold_modulo_regions(
+ &obligation.with(
+ selcx.tcx(),
+ ty::Binder::dummy(
+ selcx.tcx().at(obligation.cause.span()).mk_trait_ref(LangItem::Sized, [self_ty]),
+ )
+ .without_const(),
+ ),
+ ) =>
+ {
+ true
+ }
+
+ // FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
+ ty::Param(_)
+ | ty::Projection(..)
+ | ty::Opaque(..)
+ | ty::Bound(..)
+ | ty::Placeholder(..)
+ | ty::Infer(..)
+ | ty::Error(_) => {
+ if tail.has_infer_types() {
+ candidate_set.mark_ambiguous();
+ }
+ false
}
- false
}
+ } else {
+ bug!("unexpected builtin trait with associated type: {poly_trait_ref:?}")
}
}
super::ImplSource::Param(..) => {
false
}
super::ImplSource::AutoImpl(..)
- | super::ImplSource::Builtin(..)
| super::ImplSource::TraitUpcasting(_)
| super::ImplSource::ConstDestruct(_) => {
// These traits have no associated types.
super::ImplSource::Future(data) => confirm_future_candidate(selcx, obligation, data),
super::ImplSource::Closure(data) => confirm_closure_candidate(selcx, obligation, data),
super::ImplSource::FnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data),
- super::ImplSource::DiscriminantKind(data) => {
- confirm_discriminant_kind_candidate(selcx, obligation, data)
- }
- super::ImplSource::Pointee(data) => confirm_pointee_candidate(selcx, obligation, data),
+ super::ImplSource::Builtin(data) => confirm_builtin_candidate(selcx, obligation, data),
super::ImplSource::Object(_)
| super::ImplSource::AutoImpl(..)
| super::ImplSource::Param(..)
- | super::ImplSource::Builtin(..)
| super::ImplSource::TraitUpcasting(_)
| super::ImplSource::TraitAlias(..)
| super::ImplSource::ConstDestruct(_) => {
.with_addl_obligations(obligations)
}
-fn confirm_discriminant_kind_candidate<'cx, 'tcx>(
+fn confirm_builtin_candidate<'cx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
- _: ImplSourceDiscriminantKindData,
+ data: ImplSourceBuiltinData<PredicateObligation<'tcx>>,
) -> Progress<'tcx> {
let tcx = selcx.tcx();
-
- let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty());
- // We get here from `poly_project_and_unify_type` which replaces bound vars
- // with placeholders
- debug_assert!(!self_ty.has_escaping_bound_vars());
+ let self_ty = obligation.predicate.self_ty();
let substs = tcx.mk_substs([self_ty.into()].iter());
-
- let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
-
- let predicate = ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy { substs, item_def_id: discriminant_def_id },
- term: self_ty.discriminant_ty(tcx).into(),
+ let lang_items = tcx.lang_items();
+ let item_def_id = obligation.predicate.item_def_id;
+ let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
+ let (term, obligations) = if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
+ let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
+ assert_eq!(discriminant_def_id, item_def_id);
+
+ (self_ty.discriminant_ty(tcx).into(), Vec::new())
+ } else if lang_items.pointee_trait() == Some(trait_def_id) {
+ let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
+ assert_eq!(metadata_def_id, item_def_id);
+
+ let mut obligations = Vec::new();
+ let (metadata_ty, check_is_sized) = self_ty.ptr_metadata_ty(tcx, |ty| {
+ normalize_with_depth_to(
+ selcx,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ ty,
+ &mut obligations,
+ )
+ });
+ if check_is_sized {
+ let sized_predicate = ty::Binder::dummy(
+ tcx.at(obligation.cause.span()).mk_trait_ref(LangItem::Sized, [self_ty]),
+ )
+ .without_const();
+ obligations.push(obligation.with(tcx, sized_predicate));
+ }
+ (metadata_ty.into(), obligations)
+ } else {
+ bug!("unexpected builtin trait with associated type: {:?}", obligation.predicate);
};
- // We get here from `poly_project_and_unify_type` which replaces bound vars
- // with placeholders, so dummy is okay here.
- confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
-}
-
-fn confirm_pointee_candidate<'cx, 'tcx>(
- selcx: &mut SelectionContext<'cx, 'tcx>,
- obligation: &ProjectionTyObligation<'tcx>,
- _: ImplSourcePointeeData,
-) -> Progress<'tcx> {
- let tcx = selcx.tcx();
- let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty());
-
- let mut obligations = vec![];
- let (metadata_ty, check_is_sized) = self_ty.ptr_metadata_ty(tcx, |ty| {
- normalize_with_depth_to(
- selcx,
- obligation.param_env,
- obligation.cause.clone(),
- obligation.recursion_depth + 1,
- ty,
- &mut obligations,
- )
- });
- if check_is_sized {
- let sized_predicate = ty::Binder::dummy(
- tcx.at(obligation.cause.span).mk_trait_ref(LangItem::Sized, [self_ty]),
- )
- .without_const();
- obligations.push(obligation.with(tcx, sized_predicate));
- }
-
- let substs = tcx.mk_substs([self_ty.into()].iter());
- let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, Some(obligation.cause.span));
-
- let predicate = ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy { substs, item_def_id: metadata_def_id },
- term: metadata_ty.into(),
- };
+ let predicate =
+ ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { substs, item_def_id }, term };
confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
.with_addl_obligations(obligations)
+ .with_addl_obligations(data.nested)
}
fn confirm_fn_pointer_candidate<'cx, 'tcx>(