Skip to content

Commit b3dc15d

Browse files
committed
Normalize projections before translating them
1 parent 95101a5 commit b3dc15d

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

frontend/exporter/src/traits.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ mod resolution;
66
mod utils;
77
#[cfg(feature = "rustc")]
88
pub use utils::{
9-
erase_and_norm, implied_predicates, predicates_defined_on, required_predicates, self_predicate,
10-
Predicates, ToPolyTraitRef,
9+
erase_and_norm, erase_free_regions, implied_predicates, normalize, predicates_defined_on,
10+
required_predicates, self_predicate, Predicates, ToPolyTraitRef,
1111
};
1212

1313
#[cfg(feature = "rustc")]

frontend/exporter/src/traits/utils.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,27 @@ pub fn implied_predicates<'tcx>(
169169
}
170170
}
171171

172+
/// Normalize a value.
173+
pub fn normalize<'tcx, T>(tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>, value: T) -> T
174+
where
175+
T: TypeFoldable<TyCtxt<'tcx>> + Copy,
176+
{
177+
use rustc_infer::infer::TyCtxtInferExt;
178+
use rustc_middle::traits::ObligationCause;
179+
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
180+
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
181+
infcx
182+
.at(&ObligationCause::dummy(), param_env)
183+
.query_normalize(value)
184+
// We ignore the generated outlives relations. Unsure what we should do with them.
185+
.map(|x| x.value)
186+
.unwrap_or(value)
187+
}
188+
172189
/// Erase free regions from the given value. Largely copied from `tcx.erase_regions`, but also
173190
/// erases bound regions that are bound outside `value`, so we can call this function inside a
174191
/// `Binder`.
175-
fn erase_free_regions<'tcx, T>(tcx: TyCtxt<'tcx>, value: T) -> T
192+
pub fn erase_free_regions<'tcx, T>(tcx: TyCtxt<'tcx>, value: T) -> T
176193
where
177194
T: TypeFoldable<TyCtxt<'tcx>>,
178195
{

frontend/exporter/src/types/ty.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -804,7 +804,17 @@ impl Alias {
804804
alias_ty: &ty::AliasTy<'tcx>,
805805
) -> TyKind {
806806
let tcx = s.base().tcx;
807+
let typing_env = s.typing_env();
807808
use rustc_type_ir::AliasTyKind as RustAliasKind;
809+
810+
// Try to normalize the alias first.
811+
let ty = ty::Ty::new_alias(tcx, *alias_kind, *alias_ty);
812+
let ty = crate::traits::normalize(tcx, typing_env, ty);
813+
let ty::Alias(alias_kind, alias_ty) = ty.kind() else {
814+
let ty: Ty = ty.sinto(s);
815+
return ty.kind().clone();
816+
};
817+
808818
let kind = match alias_kind {
809819
RustAliasKind::Projection => {
810820
let trait_ref = alias_ty.trait_ref(tcx);
@@ -820,7 +830,7 @@ impl Alias {
820830
// yet we dont have a binder around (could even be several). Binding this correctly
821831
// is therefore difficult. Since our trait resolution ignores lifetimes anyway, we
822832
// just erase them. See also https://github.com/hacspec/hax/issues/747.
823-
let trait_ref = crate::traits::erase_and_norm(tcx, s.typing_env(), trait_ref);
833+
let trait_ref = crate::traits::erase_free_regions(tcx, trait_ref);
824834
AliasKind::Projection {
825835
assoc_item: tcx.associated_item(alias_ty.def_id).sinto(s),
826836
impl_expr: solve_trait(s, ty::Binder::dummy(trait_ref)),

0 commit comments

Comments
 (0)