1use std::iter;
2
3use flux_common::{bug, iter::IterExt, tracked_span_bug};
4use flux_middle::{
5 global_env::GlobalEnv,
6 queries::{QueryErr, QueryResult},
7 query_bug,
8 rty::{
9 self, AliasKind, AliasReft, AliasTerm, AliasTy, BaseTy, Binder, Clause, ClauseKind, Const,
10 ConstKind, EarlyBinder, Expr, ExprKind, GenericArg, List, ProjectionPredicate, RefineArgs,
11 Region, Sort, SubsetTy, SubsetTyCtor, Ty, TyKind, TyOrBase,
12 fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable, TypeVisitable},
13 refining::Refiner,
14 subst::{GenericsSubstDelegate, GenericsSubstFolder},
15 },
16};
17use flux_rustc_bridge::{ToRustc, lowering::Lower};
18use itertools::izip;
19use rustc_hir::def_id::DefId;
20use rustc_infer::traits::{BuiltinImplSource, Obligation};
21use rustc_middle::{
22 traits::{ImplSource, ObligationCause},
23 ty::{TyCtxt, Variance},
24};
25use rustc_trait_selection::{
26 solve::deeply_normalize,
27 traits::{FulfillmentError, SelectionContext},
28};
29use rustc_type_ir::TypeVisitableExt;
30
31use crate::{
32 infer::{InferCtxtAt, InferResult},
33 refine_tree::Scope,
34};
35
36pub trait NormalizeExt: TypeFoldable {
37 fn deeply_normalize(&self, infcx: &mut InferCtxtAt) -> QueryResult<Self>;
38
39 fn deeply_normalize_sorts<'tcx>(
41 &self,
42 def_id: DefId,
43 genv: GlobalEnv<'_, 'tcx>,
44 infcx: &rustc_infer::infer::InferCtxt<'tcx>,
45 ) -> QueryResult<Self>;
46}
47
48impl<T: TypeFoldable> NormalizeExt for T {
49 fn deeply_normalize(&self, infcx: &mut InferCtxtAt) -> QueryResult<Self> {
50 let span = infcx.span;
51 let infcx_orig = &mut infcx.infcx;
52 let mut infcx = infcx_orig.branch();
53 let infcx = infcx.at(span);
54 let mut normalizer = Normalizer::new(infcx)?;
55 self.erase_regions().try_fold_with(&mut normalizer)
56 }
57
58 fn deeply_normalize_sorts<'tcx>(
59 &self,
60 def_id: DefId,
61 genv: GlobalEnv<'_, 'tcx>,
62 infcx: &rustc_infer::infer::InferCtxt<'tcx>,
63 ) -> QueryResult<Self> {
64 let mut normalizer = SortNormalizer::new(def_id, genv, infcx);
65 self.erase_regions().try_fold_with(&mut normalizer)
66 }
67}
68
69struct Normalizer<'a, 'infcx, 'genv, 'tcx> {
70 infcx: InferCtxtAt<'a, 'infcx, 'genv, 'tcx>,
71 selcx: SelectionContext<'infcx, 'tcx>,
72 param_env: List<Clause>,
73 scope: Scope,
74}
75
76impl<'a, 'infcx, 'genv, 'tcx> Normalizer<'a, 'infcx, 'genv, 'tcx> {
77 fn new(infcx: InferCtxtAt<'a, 'infcx, 'genv, 'tcx>) -> QueryResult<Self> {
78 let predicates = infcx.genv.predicates_of(infcx.def_id)?;
79 let param_env = predicates.instantiate_identity().predicates.clone();
80 let selcx = SelectionContext::new(infcx.region_infcx);
81 let scope = infcx.cursor().marker().scope().unwrap();
82 Ok(Normalizer { infcx, selcx, param_env, scope })
83 }
84
85 fn normalize_projection_ty(
86 &mut self,
87 obligation: &AliasTerm,
88 ) -> QueryResult<(bool, SubsetTyCtor)> {
89 let obligation = &obligation.try_fold_with(self)?;
93
94 let mut candidates = vec![];
95 self.assemble_candidates_from_param_env(obligation, &mut candidates);
96 self.assemble_candidates_from_trait_def(obligation, &mut candidates)
97 .unwrap_or_else(|err| tracked_span_bug!("{err:?}"));
98 self.assemble_candidates_from_impls(obligation, &mut candidates)?;
99 if candidates.is_empty() {
100 let (changed, ty_ctor) = normalize_projection_ty_with_rustc(
105 self.genv(),
106 self.def_id(),
107 self.infcx.region_infcx,
108 obligation,
109 )?;
110 return Ok((changed, ty_ctor));
111 }
112 if candidates.len() > 1 {
113 bug!("ambiguity when resolving `{obligation:?}` in {:?}", self.def_id());
114 }
115 let ctor = self.confirm_candidate(candidates.pop().unwrap(), obligation)?;
116 Ok((true, ctor))
117 }
118
119 fn find_resolved_predicates(
120 &self,
121 subst: &mut TVarSubst,
122 preds: Vec<EarlyBinder<ProjectionPredicate>>,
123 ) -> (Vec<ProjectionPredicate>, Vec<EarlyBinder<ProjectionPredicate>>) {
124 let mut resolved = vec![];
125 let mut unresolved = vec![];
126 for pred in preds {
127 let term = pred.clone().skip_binder().term;
128 let alias_term = pred.clone().map(|p| p.projection_term);
129 match subst.instantiate_partial(alias_term) {
130 Some(projection_term) => {
131 let pred = ProjectionPredicate { projection_term, term };
132 resolved.push(pred);
133 }
134 None => unresolved.push(pred.clone()),
135 }
136 }
137 (resolved, unresolved)
138 }
139
140 fn resolve_projection_predicates(
142 &mut self,
143 subst: &mut TVarSubst,
144 impl_def_id: DefId,
145 ) -> QueryResult {
146 let mut projection_preds: Vec<_> = self
147 .genv()
148 .predicates_of(impl_def_id)?
149 .skip_binder()
150 .predicates
151 .iter()
152 .filter_map(|pred| {
153 if let ClauseKind::Projection(pred) = pred.kind_skipping_binder() {
154 Some(EarlyBinder(pred.clone()))
155 } else {
156 None
157 }
158 })
159 .collect();
160
161 while !projection_preds.is_empty() {
162 let (resolved, unresolved) = self.find_resolved_predicates(subst, projection_preds);
163
164 if resolved.is_empty() {
165 break; }
167 for p in resolved {
168 let (_, ctor) = self.normalize_projection_ty(&p.projection_term)?;
169 subst.subset_tys(&p.term, &ctor);
170 }
171 projection_preds = unresolved;
172 }
173 Ok(())
174 }
175
176 fn confirm_candidate(
177 &mut self,
178 candidate: Candidate,
179 obligation: &AliasTerm,
180 ) -> QueryResult<SubsetTyCtor> {
181 let tcx = self.tcx();
182 match candidate {
183 Candidate::ParamEnv(pred) | Candidate::TraitDef(pred) => {
184 let rustc_obligation = obligation.to_rustc(tcx);
185 let parent_id = rustc_obligation.trait_ref(tcx).def_id;
186 if tcx.is_fn_trait(parent_id) {
188 let res = self
189 .fn_subtype_projection_ty(pred, obligation)
190 .unwrap_or_else(|err| tracked_span_bug!("{err:?}"));
191 Ok(res)
192 } else {
193 Ok(pred.skip_binder().term)
194 }
195 }
196 Candidate::UserDefinedImpl(impl_def_id) => {
197 let impl_trait_ref = self.genv().impl_trait_ref(impl_def_id)?.skip_binder();
215
216 let generics = self.tcx().generics_of(impl_def_id);
217
218 let mut subst = TVarSubst::new(generics);
219 for (a, b) in iter::zip(&impl_trait_ref.args, &obligation.args) {
220 subst.generic_args(a, b);
221 }
222
223 self.resolve_projection_predicates(&mut subst, impl_def_id)?;
225
226 let mut args = subst.finish(self.tcx(), generics)?;
227
228 args.extend(
233 obligation
234 .args
235 .iter()
236 .skip(impl_trait_ref.args.len())
237 .cloned(),
238 );
239
240 let assoc_type_id = tcx
243 .associated_items(impl_def_id)
244 .in_definition_order()
245 .find(|item| item.trait_item_def_id() == Some(obligation.def_id()))
246 .map(|item| item.def_id)
247 .ok_or_else(|| {
248 query_bug!("no associated type for {obligation:?} in impl {impl_def_id:?}")
249 })?;
250 Ok(self
251 .genv()
252 .type_of(assoc_type_id)?
253 .instantiate(tcx, &args, &[])
254 .expect_subset_ty_ctor())
255 }
256 }
257 }
258
259 fn fn_subtype_projection_ty(
260 &mut self,
261 actual: Binder<ProjectionPredicate>,
262 oblig: &AliasTerm,
263 ) -> InferResult<SubsetTyCtor> {
264 let obligs: Vec<_> = oblig
266 .args
267 .iter()
268 .map(|arg| {
269 match arg {
270 GenericArg::Ty(ty) => GenericArg::Ty(self.infcx.unpack(ty)),
271 GenericArg::Base(ctor) => GenericArg::Ty(self.infcx.unpack(&ctor.to_ty())),
272 _ => arg.clone(),
273 }
274 })
275 .collect();
276
277 let span = self.infcx.span;
278 let mut infcx = self.infcx.at(span);
279
280 let actual = infcx.ensure_resolved_evars(|infcx| {
281 let actual = actual
283 .replace_bound_vars(
284 |_| rty::ReErased,
285 |sort, mode, _| infcx.fresh_infer_var(sort, mode),
286 )
287 .deeply_normalize(infcx)?;
288
289 let actuals = actual.projection_term.args.iter().map(|arg| {
290 match arg {
291 GenericArg::Base(ctor) => GenericArg::Ty(ctor.to_ty()),
292 _ => arg.clone(),
293 }
294 });
295
296 for (a, b) in izip!(actuals.skip(1), obligs.iter().skip(1)) {
298 infcx.subtyping_generic_args(
299 Variance::Contravariant,
300 &a,
301 b,
302 crate::infer::ConstrReason::Predicate,
303 )?;
304 }
305 Ok(actual)
306 })?;
307 let actual = infcx.fully_resolve_evars(&actual);
309
310 let oblig_term = actual.term.with_holes().replace_holes(|binders, kind| {
312 assert!(kind == rty::HoleKind::Pred);
313 let scope = &self.scope;
314 infcx.fresh_kvar_in_scope(binders, scope)
315 });
316
317 infcx.subtyping(
319 &actual.term.to_ty(),
320 &oblig_term.to_ty(),
321 crate::infer::ConstrReason::Predicate,
322 )?;
323 Ok(oblig_term)
325 }
326
327 fn assemble_candidates_from_predicates(
328 &mut self,
329 predicates: &List<Clause>,
330 obligation: &AliasTerm,
331 ctor: fn(Binder<ProjectionPredicate>) -> Candidate,
332 candidates: &mut Vec<Candidate>,
333 ) {
334 let tcx = self.tcx();
335 let rustc_obligation = obligation.to_rustc(tcx);
336
337 for predicate in predicates {
338 if let Some(pred) = predicate.as_projection_clause()
339 && pred.skip_binder_ref().projection_term.to_rustc(tcx) == rustc_obligation
340 {
341 candidates.push(ctor(pred));
342 }
343 }
344 }
345
346 fn assemble_candidates_from_param_env(
347 &mut self,
348 obligation: &AliasTerm,
349 candidates: &mut Vec<Candidate>,
350 ) {
351 let predicates = self.param_env.clone();
352 self.assemble_candidates_from_predicates(
353 &predicates,
354 obligation,
355 Candidate::ParamEnv,
356 candidates,
357 );
358 }
359
360 fn assemble_candidates_from_trait_def(
361 &mut self,
362 obligation: &AliasTerm,
363 candidates: &mut Vec<Candidate>,
364 ) -> InferResult {
365 if let GenericArg::Base(ctor) = &obligation.args[0]
366 && let BaseTy::Alias(alias_ty @ AliasTy { kind: AliasKind::Opaque { def_id }, .. }) =
367 ctor.as_bty_skipping_binder()
368 {
369 debug_assert!(!alias_ty.has_escaping_bvars());
370 let bounds = self.genv().item_bounds(*def_id)?.instantiate(
371 self.tcx(),
372 &alias_ty.args,
373 &alias_ty.refine_args,
374 );
375 self.assemble_candidates_from_predicates(
376 &bounds,
377 obligation,
378 Candidate::TraitDef,
379 candidates,
380 );
381 }
382 Ok(())
383 }
384
385 fn assemble_candidates_from_impls(
386 &mut self,
387 obligation: &AliasTerm,
388 candidates: &mut Vec<Candidate>,
389 ) -> QueryResult {
390 let trait_ref = obligation.to_rustc(self.tcx()).trait_ref(self.tcx());
391 let trait_ref = self.tcx().erase_and_anonymize_regions(trait_ref);
392 let trait_pred = Obligation::new(
393 self.tcx(),
394 ObligationCause::dummy(),
395 self.rustc_param_env(),
396 trait_ref,
397 );
398 if trait_pred.has_escaping_bound_vars() {
401 tracked_span_bug!();
402 }
403 match self.selcx.select(&trait_pred) {
404 Ok(Some(ImplSource::UserDefined(impl_data))) => {
405 candidates.push(Candidate::UserDefinedImpl(impl_data.impl_def_id));
406 }
407 Ok(_) => (),
408 Err(e) => bug!("error selecting {trait_pred:?}: {e:?}"),
409 }
410 Ok(())
411 }
412
413 fn def_id(&self) -> DefId {
414 self.infcx.def_id
415 }
416
417 fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
418 self.infcx.genv
419 }
420
421 fn tcx(&self) -> TyCtxt<'tcx> {
422 self.selcx.tcx()
423 }
424
425 fn rustc_param_env(&self) -> rustc_middle::ty::ParamEnv<'tcx> {
426 self.selcx.tcx().param_env(self.def_id())
427 }
428}
429
430impl FallibleTypeFolder for Normalizer<'_, '_, '_, '_> {
431 type Error = QueryErr;
432
433 fn try_fold_sort(&mut self, sort: &Sort) -> Result<Sort, Self::Error> {
434 match sort {
435 Sort::Alias(AliasTy { kind: AliasKind::Free { def_id }, args, refine_args }) => {
436 self.genv()
437 .normalize_free_alias_sort(*def_id, args, refine_args)?
438 .try_fold_with(self)
439 }
440 Sort::Alias(alias_ty @ AliasTy { kind: AliasKind::Projection { .. }, .. }) => {
441 let (changed, ctor) = self.normalize_projection_ty(&alias_ty.to_alias_term())?;
442 let sort = ctor.sort();
443 if changed { sort.try_fold_with(self) } else { Ok(sort) }
444 }
445 _ => sort.try_super_fold_with(self),
446 }
447 }
448
449 fn try_fold_ty(&mut self, ty: &Ty) -> Result<Ty, Self::Error> {
455 match ty.kind() {
456 TyKind::Indexed(
457 BaseTy::Alias(AliasTy { kind: AliasKind::Free { def_id }, args, refine_args }),
458 idx,
459 ) => {
460 Ok(self
461 .genv()
462 .type_of(*def_id)?
463 .instantiate(self.tcx(), args, refine_args)
464 .expect_ctor()
465 .replace_bound_reft(idx))
466 }
467 TyKind::Indexed(
468 BaseTy::Alias(alias_ty @ AliasTy { kind: AliasKind::Projection { .. }, .. }),
469 idx,
470 ) => {
471 let (changed, ctor) = self.normalize_projection_ty(&alias_ty.to_alias_term())?;
472 let ty = ctor.replace_bound_reft(idx).to_ty();
473 if changed { ty.try_fold_with(self) } else { Ok(ty) }
474 }
475 _ => ty.try_super_fold_with(self),
476 }
477 }
478
479 fn try_fold_subset_ty(&mut self, sty: &SubsetTy) -> Result<SubsetTy, Self::Error> {
480 match &sty.bty {
481 BaseTy::Alias(AliasTy { kind: AliasKind::Free { .. }, .. }) => {
482 tracked_span_bug!()
487 }
488 BaseTy::Alias(alias_ty @ AliasTy { kind: AliasKind::Projection { .. }, .. }) => {
489 let (changed, ctor) = self.normalize_projection_ty(&alias_ty.to_alias_term())?;
490 let ty = ctor.replace_bound_reft(&sty.idx).strengthen(&sty.pred);
491 if changed { ty.try_fold_with(self) } else { Ok(ty) }
492 }
493 _ => sty.try_super_fold_with(self),
494 }
495 }
496
497 fn try_fold_expr(&mut self, expr: &Expr) -> Result<Expr, Self::Error> {
498 if let ExprKind::Alias(alias_pred, refine_args) = expr.kind() {
499 let (changed, e) = normalize_alias_reft(
500 self.genv(),
501 self.def_id(),
502 self.selcx.infcx,
503 alias_pred,
504 refine_args,
505 )?;
506 if changed { e.try_fold_with(self) } else { Ok(e) }
507 } else {
508 expr.try_super_fold_with(self)
509 }
510 }
511
512 fn try_fold_const(&mut self, c: &Const) -> Result<Const, Self::Error> {
513 let c = c.to_rustc(self.tcx());
514 rustc_trait_selection::traits::evaluate_const(self.selcx.infcx, c, self.rustc_param_env())
515 .lower(self.tcx())
516 .map_err(|e| QueryErr::unsupported(self.def_id(), e.into_err()))
517 }
518}
519
520#[derive(Debug)]
521pub enum Candidate {
522 UserDefinedImpl(DefId),
523 ParamEnv(Binder<ProjectionPredicate>),
524 TraitDef(Binder<ProjectionPredicate>),
525}
526
527#[derive(Debug)]
528struct TVarSubst {
529 args: Vec<Option<GenericArg>>,
530}
531
532impl GenericsSubstDelegate for &TVarSubst {
533 type Error = ();
534
535 fn ty_for_param(&mut self, param_ty: rustc_middle::ty::ParamTy) -> Result<Ty, Self::Error> {
536 match self.args.get(param_ty.index as usize) {
537 Some(Some(GenericArg::Ty(ty))) => Ok(ty.clone()),
538 Some(None) => Err(()),
539 arg => tracked_span_bug!("expected type for generic parameter, found `{arg:?}`"),
540 }
541 }
542
543 fn sort_for_param(&mut self, param_ty: rustc_middle::ty::ParamTy) -> Result<Sort, Self::Error> {
544 match self.args.get(param_ty.index as usize) {
545 Some(Some(GenericArg::Base(ctor))) => Ok(ctor.sort()),
546 Some(None) => Err(()),
547 arg => tracked_span_bug!("expected type for generic parameter, found `{arg:?}`"),
548 }
549 }
550
551 fn ctor_for_param(
552 &mut self,
553 param_ty: rustc_middle::ty::ParamTy,
554 ) -> Result<SubsetTyCtor, Self::Error> {
555 match self.args.get(param_ty.index as usize) {
556 Some(Some(GenericArg::Base(ctor))) => Ok(ctor.clone()),
557 Some(None) => Err(()),
558 arg => tracked_span_bug!("expected type for generic parameter, found `{arg:?}`"),
559 }
560 }
561
562 fn region_for_param(
563 &mut self,
564 ebr: rustc_middle::ty::EarlyParamRegion,
565 ) -> Result<Region, Self::Error> {
566 match self.args.get(ebr.index as usize) {
567 Some(Some(GenericArg::Lifetime(region))) => Ok(*region),
568 Some(None) => Err(()),
569 arg => tracked_span_bug!("expected region for generic parameter, found `{arg:?}`"),
570 }
571 }
572
573 fn expr_for_param_const(&self, _param_const: rustc_middle::ty::ParamConst) -> Expr {
574 tracked_span_bug!()
575 }
576
577 fn const_for_param(&mut self, _param: &Const) -> Const {
578 tracked_span_bug!()
579 }
580}
581
582struct SortNormalizer<'infcx, 'genv, 'tcx> {
583 def_id: DefId,
584 infcx: &'infcx rustc_infer::infer::InferCtxt<'tcx>,
585 genv: GlobalEnv<'genv, 'tcx>,
586}
587
588impl<'infcx, 'genv, 'tcx> SortNormalizer<'infcx, 'genv, 'tcx> {
589 fn new(
590 def_id: DefId,
591 genv: GlobalEnv<'genv, 'tcx>,
592 infcx: &'infcx rustc_infer::infer::InferCtxt<'tcx>,
593 ) -> Self {
594 Self { def_id, infcx, genv }
595 }
596}
597
598impl FallibleTypeFolder for SortNormalizer<'_, '_, '_> {
599 type Error = QueryErr;
600 fn try_fold_sort(&mut self, sort: &Sort) -> Result<Sort, Self::Error> {
601 match sort {
602 Sort::Alias(AliasTy { kind: AliasKind::Free { def_id }, args, refine_args }) => {
603 self.genv
604 .normalize_free_alias_sort(*def_id, args, refine_args)?
605 .try_fold_with(self)
606 }
607 Sort::Alias(alias_ty @ AliasTy { kind: AliasKind::Projection { .. }, .. }) => {
608 let (changed, ctor) = normalize_projection_ty_with_rustc(
609 self.genv,
610 self.def_id,
611 self.infcx,
612 &alias_ty.to_alias_term(),
613 )?;
614 let sort = ctor.sort();
615 if changed { sort.try_fold_with(self) } else { Ok(sort) }
616 }
617 _ => sort.try_super_fold_with(self),
618 }
619 }
620}
621
622impl TVarSubst {
623 fn new(generics: &rustc_middle::ty::Generics) -> Self {
624 Self { args: vec![None; generics.count()] }
625 }
626
627 fn instantiate_partial<T: TypeFoldable>(&mut self, pred: EarlyBinder<T>) -> Option<T> {
628 let mut folder = GenericsSubstFolder::new(&*self, &[]);
629 pred.skip_binder().try_fold_with(&mut folder).ok()
630 }
631
632 fn finish<'tcx>(
633 self,
634 tcx: TyCtxt<'tcx>,
635 generics: &'tcx rustc_middle::ty::Generics,
636 ) -> QueryResult<Vec<GenericArg>> {
637 self.args
638 .into_iter()
639 .enumerate()
640 .map(|(idx, arg)| {
641 if let Some(arg) = arg {
642 Ok(arg)
643 } else {
644 let param = generics.param_at(idx, tcx);
645 Err(QueryErr::bug(
646 None,
647 format!("cannot infer substitution for {param:?} at index {idx}"),
648 ))
649 }
650 })
651 .try_collect_vec()
652 }
653
654 fn generic_args(&mut self, a: &GenericArg, b: &GenericArg) {
655 match (a, b) {
656 (GenericArg::Ty(a), GenericArg::Ty(b)) => self.tys(a, b),
657 (GenericArg::Lifetime(a), GenericArg::Lifetime(b)) => self.regions(*a, *b),
658 (GenericArg::Base(a), GenericArg::Base(b)) => {
659 self.subset_tys(a, b);
660 }
661 (GenericArg::Const(a), GenericArg::Const(b)) => self.consts(a, b),
662 _ => {}
663 }
664 }
665
666 fn tys(&mut self, a: &Ty, b: &Ty) {
667 if let TyKind::Param(param_ty) = a.kind() {
668 if !b.has_escaping_bvars() {
669 self.insert_generic_arg(param_ty.index, GenericArg::Ty(b.clone()));
670 }
671 } else {
672 let a = a.shallow_canonicalize().as_ty_or_base();
673 let b = b.shallow_canonicalize().as_ty_or_base();
674 if let (TyOrBase::Base(a_ctor), TyOrBase::Base(b_ctor)) = (a, b) {
675 self.subset_tys(&a_ctor, &b_ctor);
676 }
677 }
678 }
679
680 fn subset_tys(&mut self, a: &SubsetTyCtor, b: &SubsetTyCtor) {
681 let bty_a = a.as_bty_skipping_binder();
682 let bty_b = b.as_bty_skipping_binder();
683 if let BaseTy::Param(param_ty) = bty_a {
684 if !b.has_escaping_bvars() {
685 self.insert_generic_arg(param_ty.index, GenericArg::Base(b.clone()));
686 }
687 } else {
688 self.btys(bty_a, bty_b);
689 }
690 }
691
692 fn btys(&mut self, a: &BaseTy, b: &BaseTy) {
693 match (a, b) {
694 (BaseTy::Param(param_ty), _) => {
695 if !b.has_escaping_bvars() {
696 let sort = b.sort();
697 let ctor =
698 Binder::bind_with_sort(SubsetTy::trivial(b.clone(), Expr::nu()), sort);
699 self.insert_generic_arg(param_ty.index, GenericArg::Base(ctor));
700 }
701 }
702 (BaseTy::Adt(_, a_args), BaseTy::Adt(_, b_args)) => {
703 debug_assert_eq!(a_args.len(), b_args.len());
704 for (a_arg, b_arg) in iter::zip(a_args, b_args) {
705 self.generic_args(a_arg, b_arg);
706 }
707 }
708 (BaseTy::Array(a_ty, a_n), BaseTy::Array(b_ty, b_n)) => {
709 self.tys(a_ty, b_ty);
710 self.consts(a_n, b_n);
711 }
712 (BaseTy::Tuple(a_tys), BaseTy::Tuple(b_tys)) => {
713 debug_assert_eq!(a_tys.len(), b_tys.len());
714 for (a_ty, b_ty) in iter::zip(a_tys, b_tys) {
715 self.tys(a_ty, b_ty);
716 }
717 }
718 (BaseTy::Ref(a_re, a_ty, _), BaseTy::Ref(b_re, b_ty, _)) => {
719 self.regions(*a_re, *b_re);
720 self.tys(a_ty, b_ty);
721 }
722 (BaseTy::Slice(a_ty), BaseTy::Slice(b_ty)) => {
723 self.tys(a_ty, b_ty);
724 }
725 _ => {}
726 }
727 }
728
729 fn regions(&mut self, a: Region, b: Region) {
730 if let Region::ReEarlyParam(ebr) = a {
731 self.insert_generic_arg(ebr.index, GenericArg::Lifetime(b));
732 }
733 }
734
735 fn consts(&mut self, a: &Const, b: &Const) {
736 if let ConstKind::Param(param_const) = a.kind {
737 self.insert_generic_arg(param_const.index, GenericArg::Const(b.clone()));
738 }
739 }
740
741 fn insert_generic_arg(&mut self, idx: u32, arg: GenericArg) {
742 if let Some(old) = &self.args[idx as usize]
743 && old != &arg
744 {
745 tracked_span_bug!("ambiguous substitution: old=`{old:?}`, new: `{arg:?}`");
746 }
747 self.args[idx as usize].replace(arg);
748 }
749}
750
751fn normalize_projection_ty_with_rustc<'tcx>(
759 genv: GlobalEnv<'_, 'tcx>,
760 def_id: DefId,
761 infcx: &rustc_infer::infer::InferCtxt<'tcx>,
762 obligation: &AliasTerm,
763) -> QueryResult<(bool, SubsetTyCtor)> {
764 let tcx = genv.tcx();
765 let projection_ty = obligation.to_rustc(tcx).expect_ty();
766 let projection_ty = tcx.erase_and_anonymize_regions(projection_ty);
767 let cause = ObligationCause::dummy();
768 let param_env = tcx.param_env(def_id);
769
770 let pre_ty = projection_ty.to_ty(tcx, rustc_middle::ty::IsRigid::No);
771 let at = infcx.at(&cause, param_env);
772 let ty = deeply_normalize::<rustc_middle::ty::Ty<'tcx>, FulfillmentError>(
773 at,
774 rustc_middle::ty::Unnormalized::new(pre_ty),
775 )
776 .map_err(|err| query_bug!("{err:?}"))?;
777
778 let changed = rustc_middle::ty::set_aliases_to_non_rigid(tcx, ty).skip_normalization()
782 != rustc_middle::ty::set_aliases_to_non_rigid(tcx, pre_ty).skip_normalization();
783 let rustc_ty = ty.lower(tcx).map_err(|reason| query_bug!("{reason:?}"))?;
784
785 Ok((
786 changed,
787 Refiner::default_for_item(genv, def_id)?
788 .refine_ty_or_base(&rustc_ty)?
789 .expect_base(),
790 ))
791}
792
793pub fn structurally_normalize_expr<'tcx>(
798 genv: GlobalEnv<'_, 'tcx>,
799 def_id: DefId,
800 infcx: &rustc_infer::infer::InferCtxt<'tcx>,
801 expr: &Expr,
802) -> QueryResult<Expr> {
803 if let ExprKind::Alias(alias_pred, refine_args) = expr.kind() {
804 let (_, e) = normalize_alias_reft(genv, def_id, infcx, alias_pred, refine_args)?;
805 Ok(e)
806 } else {
807 Ok(expr.clone())
808 }
809}
810
811fn normalize_alias_reft<'tcx>(
815 genv: GlobalEnv<'_, 'tcx>,
816 def_id: DefId,
817 infcx: &rustc_infer::infer::InferCtxt<'tcx>,
818 alias_reft: &AliasReft,
819 refine_args: &RefineArgs,
820) -> QueryResult<(bool, Expr)> {
821 let tcx = genv.tcx();
822
823 let is_final = genv.assoc_refinement(alias_reft.assoc_id)?.final_;
824 if is_final {
825 let e = genv
826 .default_assoc_refinement_body(alias_reft.assoc_id)?
827 .unwrap_or_else(|| {
828 bug!("final associated refinement without body - should be caught in desugar")
829 })
830 .instantiate(genv.tcx(), &alias_reft.args, &[])
831 .apply(refine_args);
832 return Ok((true, e));
833 }
834
835 let mut selcx = SelectionContext::new(infcx);
837 let param_env = tcx.param_env(def_id);
838 let trait_ref = alias_reft.to_rustc_trait_ref(tcx);
839 let trait_ref = tcx.erase_and_anonymize_regions(trait_ref);
840 let trait_pred = Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
841
842 let impl_source = selcx
843 .select(&trait_pred)
844 .map_err(|e| query_bug!("error selecting {trait_pred:?}: {e:?}"))?;
845
846 match impl_source {
847 Some(ImplSource::UserDefined(impl_data)) => {
848 let impl_def_id = impl_data.impl_def_id;
849 let args = Refiner::default_for_item(genv, def_id)?.refine_generic_args(
850 impl_def_id,
851 &impl_data
852 .args
853 .lower(tcx)
854 .map_err(|reason| query_bug!("{reason:?}"))?,
855 )?;
856 let e = genv
857 .assoc_refinement_body_for_impl(alias_reft.assoc_id, impl_def_id)?
858 .instantiate(tcx, &args, &[])
859 .apply(refine_args);
860 Ok((true, e))
861 }
862 Some(ImplSource::Builtin(BuiltinImplSource::Misc | BuiltinImplSource::Trivial, _))
863 if let Some(body) =
864 genv.builtin_assoc_reft_body(infcx.typing_env(param_env), alias_reft) =>
865 {
866 Ok((true, body.apply(refine_args)))
867 }
868 _ => Ok((false, Expr::alias(alias_reft.clone(), refine_args.clone()))),
869 }
870}