diff options
| author | Lukas Markeffsky <@> | 2024-02-05 14:54:24 +0100 |
|---|---|---|
| committer | Lukas Markeffsky <@> | 2024-02-05 15:37:21 +0100 |
| commit | 0c1f401d98c17372d4f305602a43e53cd2ef78a6 (patch) | |
| tree | 46bcda5b2bbb282dbc4783b38b27d45812224738 /compiler/rustc_trait_selection | |
| parent | 77fb5406842d6e349b4d67289eba5a9a4a571a9a (diff) | |
| download | rust-0c1f401d98c17372d4f305602a43e53cd2ef78a6.tar.gz rust-0c1f401d98c17372d4f305602a43e53cd2ef78a6.zip | |
old solver: improve normalization of `Pointee::Metadata`
Diffstat (limited to 'compiler/rustc_trait_selection')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/project.rs | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index abbc2066eac..33298c4b750 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1916,10 +1916,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // 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 + // We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata` if able. + // Otherwise, type parameters, opaques, and unnormalized projections have + // unit metadata if they're known (e.g. by the param_env) to be sized. ty::Param(_) | ty::Alias(..) - if selcx.infcx.predicate_must_hold_modulo_regions( + if self_ty != tail || selcx.infcx.predicate_must_hold_modulo_regions( &obligation.with( selcx.tcx(), ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]), @@ -2289,7 +2290,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( 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| { + let normalize = |ty| { normalize_with_depth_to( selcx, obligation.param_env, @@ -2298,16 +2299,26 @@ fn confirm_builtin_candidate<'cx, 'tcx>( ty, &mut obligations, ) + }; + let metadata_ty = self_ty.ptr_metadata_ty_or_tail(tcx, normalize).unwrap_or_else(|tail| { + if tail == self_ty { + // This is the fallback case for type parameters, unnormalizable projections + // and opaque types. + // If the `self_ty` is `Sized`, then the metadata is `()`. + let sized_predicate = ty::TraitRef::from_lang_item( + tcx, + LangItem::Sized, + obligation.cause.span(), + [self_ty], + ); + obligations.push(obligation.with(tcx, sized_predicate)); + tcx.types.unit + } else { + // We know that `self_ty` has the same metadata as `tail`. This allows us + // to prove predicates like `Wrapper<Tail>::Metadata == Tail::Metadata`. + Ty::new_projection(tcx, metadata_def_id, [tail]) + } }); - if check_is_sized { - let sized_predicate = ty::TraitRef::from_lang_item( - tcx, - LangItem::Sized, - obligation.cause.span(), - [self_ty], - ); - obligations.push(obligation.with(tcx, sized_predicate)); - } (metadata_ty.into(), obligations) } else { bug!("unexpected builtin trait with associated type: {:?}", obligation.predicate); |
