@@ -1075,24 +1075,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
10751075 | ty::Error(_) => false,
10761076 }
10771077 } else if lang_items.pointee_trait() == Some(trait_ref.def_id) {
1078- let tail = selcx.tcx().struct_tail_with_normalize(
1079- self_ty,
1080- |ty| {
1081- // We throw away any obligations we get from this, since we normalize
1082- // and confirm these obligations once again during confirmation
1083- normalize_with_depth(
1084- selcx,
1085- obligation.param_env,
1086- obligation.cause.clone(),
1087- obligation.recursion_depth + 1,
1088- ty,
1089- )
1090- .value
1091- },
1092- || {},
1093- );
1094-
1095- match tail.kind() {
1078+ match self_ty.kind() {
10961079 ty::Bool
10971080 | ty::Char
10981081 | ty::Int(_)
@@ -1113,21 +1096,17 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
11131096 | ty::Never
11141097 // Extern types have unit metadata, according to RFC 2850
11151098 | ty::Foreign(_)
1116- // If returned by `struct_tail_without_normalization` this is a unit struct
1117- // without any fields, or not a struct, and therefore is Sized .
1099+ // The metadata of an ADT or tuple is the metadata of its tail,
1100+ // or unit if it has no tail .
11181101 | ty::Adt(..)
1119- // If returned by `struct_tail_without_normalization` this is the empty tuple.
11201102 | ty::Tuple(..)
1121- // Integers and floats are always Sized , and so have unit type metadata.
1103+ // Integers and floats are always sized , and so have unit type metadata.
11221104 | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..))
1123- // `{type error}` is sized, so its metadata must be the unit type.
1105+ // The metadata of `{type error}` is `{ type error}` .
11241106 | ty::Error(_) => true,
11251107
1126- // We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata`.
1127- ty::Param(_) | ty::Alias(..) => self_ty != tail,
1128-
1129- // FIXME: These should probably project to the tail as well.
1130- ty::Bound(..) | ty::Placeholder(..) => false,
1108+ // The metadata of these types can only be known from param env candidates.
1109+ ty::Param(_) | ty::Alias(..) | ty::Bound(..) | ty::Placeholder(..) => false,
11311110
11321111 ty::Infer(ty::TyVar(_)) => {
11331112 candidate_set.mark_ambiguous();
@@ -1485,49 +1464,93 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
14851464 let lang_items = tcx.lang_items();
14861465 let item_def_id = obligation.predicate.def_id;
14871466 let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
1488- let (term, obligations) = if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
1467+ let mut potentially_unnormalized = false;
1468+ let term = if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
14891469 let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
14901470 assert_eq!(discriminant_def_id, item_def_id);
14911471
1492- ( self_ty.discriminant_ty(tcx).into(), Vec::new() )
1472+ self_ty.discriminant_ty(tcx).into()
14931473 } else if lang_items.pointee_trait() == Some(trait_def_id) {
14941474 let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
14951475 assert_eq!(metadata_def_id, item_def_id);
14961476
1497- let mut obligations = Vec::new();
1498- let normalize = |ty| {
1499- normalize_with_depth_to(
1500- selcx,
1501- obligation.param_env,
1502- obligation.cause.clone(),
1503- obligation.recursion_depth + 1,
1504- ty,
1505- &mut obligations,
1506- )
1507- };
1508- let metadata_ty = self_ty.ptr_metadata_ty_or_tail(tcx, normalize).unwrap_or_else(|tail| {
1509- if tail == self_ty {
1477+ let metadata_ty = match self_ty.kind() {
1478+ ty::Bool
1479+ | ty::Char
1480+ | ty::Int(..)
1481+ | ty::Uint(..)
1482+ | ty::Float(..)
1483+ | ty::Array(..)
1484+ | ty::RawPtr(..)
1485+ | ty::Ref(..)
1486+ | ty::FnDef(..)
1487+ | ty::FnPtr(..)
1488+ | ty::Closure(..)
1489+ | ty::CoroutineClosure(..)
1490+ | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
1491+ | ty::Coroutine(..)
1492+ | ty::CoroutineWitness(..)
1493+ | ty::Never
1494+ | ty::Foreign(..)
1495+ | ty::Dynamic(_, _, ty::DynStar) => tcx.types.unit,
1496+
1497+ ty::Error(e) => Ty::new_error(tcx, *e),
1498+
1499+ ty::Str | ty::Slice(_) => tcx.types.usize,
1500+
1501+ ty::Dynamic(_, _, ty::Dyn) => {
1502+ let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
1503+ tcx.type_of(dyn_metadata).instantiate(tcx, &[self_ty.into()])
1504+ }
1505+
1506+ ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() {
1507+ None => tcx.types.unit,
1508+ Some(tail_def) => {
1509+ // We know that `self_ty` has the same metadata as its tail. This allows us
1510+ // to prove predicates like `Wrapper<Tail>::Metadata == Tail::Metadata`.
1511+ let tail_ty = tail_def.ty(tcx, args);
1512+ potentially_unnormalized = true;
1513+ Ty::new_projection(tcx, metadata_def_id, [tail_ty])
1514+ }
1515+ },
1516+ ty::Adt(_, _) => tcx.types.unit,
1517+
1518+ ty::Tuple(elements) => match elements.last() {
1519+ None => tcx.types.unit,
1520+ Some(&tail_ty) => {
1521+ potentially_unnormalized = true;
1522+ Ty::new_projection(tcx, metadata_def_id, [tail_ty])
1523+ }
1524+ },
1525+
1526+ ty::Param(_)
1527+ | ty::Alias(..)
1528+ | ty::Bound(..)
1529+ | ty::Placeholder(..)
1530+ | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
15101531 span_bug!(
15111532 obligation.cause.span,
15121533 "`<{self_ty:?} as Pointee>::Metadata` projection candidate assembled, \
15131534 but we cannot project further",
15141535 );
15151536 }
1516- // We know that `self_ty` has the same metadata as `tail`. This allows us
1517- // to prove predicates like `Wrapper<Tail>::Metadata == Tail::Metadata`.
1518- Ty::new_projection(tcx, metadata_def_id, [tail])
1519- });
1520- (metadata_ty.into(), obligations)
1537+ };
1538+
1539+ metadata_ty.into()
15211540 } else {
15221541 bug!("unexpected builtin trait with associated type: {:?}", obligation.predicate);
15231542 };
15241543
15251544 let predicate =
15261545 ty::ProjectionPredicate { projection_ty: ty::AliasTy::new(tcx, item_def_id, args), term };
15271546
1528- confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
1529- .with_addl_obligations(obligations)
1530- .with_addl_obligations(data)
1547+ confirm_param_env_candidate(
1548+ selcx,
1549+ obligation,
1550+ ty::Binder::dummy(predicate),
1551+ potentially_unnormalized,
1552+ )
1553+ .with_addl_obligations(data)
15311554}
15321555
15331556fn confirm_fn_pointer_candidate<'cx, 'tcx>(
0 commit comments