Skip to content

Commit 4b26bb5

Browse files
committed
Extract select_inherent_assoc_type_candidates
1 parent 8694b09 commit 4b26bb5

File tree

1 file changed

+95
-79
lines changed
  • compiler/rustc_hir_analysis/src/astconv

1 file changed

+95
-79
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

+95-79
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,12 @@ use rustc_hir::def_id::{DefId, LocalDefId};
2727
use rustc_hir::intravisit::{walk_generics, Visitor as _};
2828
use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
2929
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
30-
use rustc_infer::traits::ObligationCause;
30+
use rustc_infer::traits::{Obligation, ObligationCause};
3131
use rustc_middle::middle::stability::AllowUnstable;
3232
use rustc_middle::ty::GenericParamDefKind;
3333
use rustc_middle::ty::{
34-
self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, Ty, TyCtxt, TypeVisitableExt,
34+
self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, ParamEnv, Predicate, Ty, TyCtxt,
35+
TypeVisitableExt,
3536
};
3637
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
3738
use rustc_span::edit_distance::find_best_match_for_name;
@@ -1607,7 +1608,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16071608
let param_env = tcx.param_env(block.owner);
16081609
let cause = ObligationCause::misc(span, block.owner.def_id);
16091610

1610-
let mut fulfillment_errors = Vec::new();
16111611
let mut universes = if self_ty.has_escaping_bound_vars() {
16121612
vec![None; self_ty.outer_exclusive_binder().as_usize()]
16131613
} else {
@@ -1619,94 +1619,110 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16191619
&mut universes,
16201620
self_ty,
16211621
|self_ty| {
1622+
let tcx = self.tcx();
16221623
let InferOk { value: self_ty, obligations } =
16231624
infcx.at(&cause, param_env).normalize(self_ty);
16241625

1625-
let mut applicable_candidates: Vec<_> = candidates
1626-
.iter()
1627-
.copied()
1628-
.filter(|&(impl_, _)| {
1629-
infcx.probe(|_| {
1630-
let ocx = ObligationCtxt::new(infcx);
1631-
ocx.register_obligations(obligations.clone());
1632-
1633-
let impl_args = infcx.fresh_args_for_item(span, impl_);
1634-
let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
1635-
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
1636-
1637-
// Check that the self types can be related.
1638-
if ocx
1639-
.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty)
1640-
.is_err()
1641-
{
1642-
return false;
1643-
}
1644-
1645-
// Check whether the impl imposes obligations we have to worry about.
1646-
let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
1647-
let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
1648-
let impl_obligations = traits::predicates_for_generics(
1649-
|_, _| cause.clone(),
1650-
param_env,
1651-
impl_bounds,
1652-
);
1653-
ocx.register_obligations(impl_obligations);
1626+
let (impl_, (assoc_item, def_scope)) = self.select_inherent_assoc_type_candidates(
1627+
infcx,
1628+
name,
1629+
span,
1630+
self_ty,
1631+
cause,
1632+
param_env,
1633+
obligations,
1634+
candidates,
1635+
)?;
1636+
1637+
self.check_assoc_ty(assoc_item, name, def_scope, block, span);
1638+
1639+
// FIXME(fmease): Currently creating throwaway `parent_args` to please
1640+
// `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
1641+
// not require the parent args logic.
1642+
let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
1643+
let args =
1644+
self.create_args_for_associated_item(span, assoc_item, segment, parent_args);
1645+
let args = tcx.mk_args_from_iter(
1646+
std::iter::once(ty::GenericArg::from(self_ty))
1647+
.chain(args.into_iter().skip(parent_args.len())),
1648+
);
16541649

1655-
let mut errors = ocx.select_where_possible();
1656-
if !errors.is_empty() {
1657-
fulfillment_errors.append(&mut errors);
1658-
return false;
1659-
}
1650+
let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args));
16601651

1661-
true
1662-
})
1663-
})
1664-
.collect();
1652+
Ok(Some((ty, assoc_item)))
1653+
},
1654+
)
1655+
}
16651656

1666-
if applicable_candidates.len() > 1 {
1667-
return Err(self.complain_about_ambiguous_inherent_assoc_type(
1668-
name,
1669-
applicable_candidates
1670-
.into_iter()
1671-
.map(|(_, (candidate, _))| candidate)
1672-
.collect(),
1673-
span,
1674-
));
1675-
}
1657+
fn select_inherent_assoc_type_candidates(
1658+
&self,
1659+
infcx: &InferCtxt<'tcx>,
1660+
name: Ident,
1661+
span: Span,
1662+
self_ty: Ty<'tcx>,
1663+
cause: ObligationCause<'tcx>,
1664+
param_env: ParamEnv<'tcx>,
1665+
obligations: Vec<Obligation<'tcx, Predicate<'tcx>>>,
1666+
candidates: Vec<(DefId, (DefId, DefId))>,
1667+
) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
1668+
let tcx = self.tcx();
1669+
let mut fulfillment_errors = Vec::new();
16761670

1677-
if let Some((impl_, (assoc_item, def_scope))) = applicable_candidates.pop() {
1678-
self.check_assoc_ty(assoc_item, name, def_scope, block, span);
1671+
let applicable_candidates: Vec<_> = candidates
1672+
.iter()
1673+
.copied()
1674+
.filter(|&(impl_, _)| {
1675+
infcx.probe(|_| {
1676+
let ocx = ObligationCtxt::new(infcx);
1677+
ocx.register_obligations(obligations.clone());
1678+
1679+
let impl_args = infcx.fresh_args_for_item(span, impl_);
1680+
let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
1681+
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
1682+
1683+
// Check that the self types can be related.
1684+
if ocx.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() {
1685+
return false;
1686+
}
16791687

1680-
// FIXME(fmease): Currently creating throwaway `parent_args` to please
1681-
// `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
1682-
// not require the parent args logic.
1683-
let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
1684-
let args = self.create_args_for_associated_item(
1685-
span,
1686-
assoc_item,
1687-
segment,
1688-
parent_args,
1689-
);
1690-
let args = tcx.mk_args_from_iter(
1691-
std::iter::once(ty::GenericArg::from(self_ty))
1692-
.chain(args.into_iter().skip(parent_args.len())),
1688+
// Check whether the impl imposes obligations we have to worry about.
1689+
let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
1690+
let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
1691+
let impl_obligations = traits::predicates_for_generics(
1692+
|_, _| cause.clone(),
1693+
param_env,
1694+
impl_bounds,
16931695
);
1696+
ocx.register_obligations(impl_obligations);
16941697

1695-
let ty =
1696-
Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args));
1698+
let mut errors = ocx.select_where_possible();
1699+
if !errors.is_empty() {
1700+
fulfillment_errors.append(&mut errors);
1701+
return false;
1702+
}
16971703

1698-
return Ok(Some((ty, assoc_item)));
1699-
}
1704+
true
1705+
})
1706+
})
1707+
.collect();
17001708

1701-
Err(self.complain_about_inherent_assoc_type_not_found(
1702-
name,
1703-
self_ty,
1704-
candidates,
1705-
fulfillment_errors,
1706-
span,
1707-
))
1708-
},
1709-
)
1709+
match &applicable_candidates[..] {
1710+
&[] => Err(self.complain_about_inherent_assoc_type_not_found(
1711+
name,
1712+
self_ty,
1713+
candidates,
1714+
fulfillment_errors,
1715+
span,
1716+
)),
1717+
1718+
&[applicable_candidate] => Ok(applicable_candidate),
1719+
1720+
&[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc_type(
1721+
name,
1722+
applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
1723+
span,
1724+
)),
1725+
}
17101726
}
17111727

17121728
fn lookup_assoc_ty(

0 commit comments

Comments
 (0)