mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 12:36:47 +00:00
Update term for use in more places
Replace use of `ty()` on term and use it in more places. This will allow more flexibility in the future, but slightly worried it allows items which are consts which only accept types.
This commit is contained in:
parent
67f56671d0
commit
e7529d6a38
@ -7,7 +7,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::subst::{GenericArgKind, Subst};
|
||||
use rustc_middle::ty::{self, OpaqueTypeKey, Term, Ty, TyCtxt, TypeFoldable, TypeVisitor};
|
||||
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor};
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::ops::ControlFlow;
|
||||
@ -584,13 +584,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
||||
debug!(?predicate);
|
||||
|
||||
if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
|
||||
if let Term::Ty(ty) = projection.term {
|
||||
if ty.references_error() {
|
||||
// No point on adding these obligations since there's a type error involved.
|
||||
return tcx.ty_error();
|
||||
}
|
||||
} else {
|
||||
todo!();
|
||||
if projection.term.references_error() {
|
||||
return tcx.ty_error();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -742,6 +742,8 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
|
||||
ast::AssocConstraintKind::Equality { ref term } => {
|
||||
match term {
|
||||
Term::Ty(ty) => involves_impl_trait(ty),
|
||||
// FIXME(...): This should check if the constant
|
||||
// involves a trait impl, but for now ignore.
|
||||
Term::Const(_) => false,
|
||||
}
|
||||
}
|
||||
|
@ -152,6 +152,19 @@ impl<'tcx> AssocItems<'tcx> {
|
||||
.find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id))
|
||||
}
|
||||
|
||||
/// Returns the associated item with the given name and any of `AssocKind`, if one exists.
|
||||
pub fn find_by_name_and_kinds(
|
||||
&self,
|
||||
tcx: TyCtxt<'_>,
|
||||
ident: Ident,
|
||||
kinds: &[AssocKind],
|
||||
parent_def_id: DefId,
|
||||
) -> Option<&ty::AssocItem> {
|
||||
self.filter_by_name_unhygienic(ident.name)
|
||||
.filter(|item| kinds.contains(&item.kind))
|
||||
.find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id))
|
||||
}
|
||||
|
||||
/// Returns the associated item with the given name in the given `Namespace`, if one exists.
|
||||
pub fn find_by_name_and_namespace(
|
||||
&self,
|
||||
|
@ -86,10 +86,14 @@ impl<'tcx> Const<'tcx> {
|
||||
if let Some(lit_input) = lit_input {
|
||||
// If an error occurred, ignore that it's a literal and leave reporting the error up to
|
||||
// mir.
|
||||
if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) {
|
||||
return Some(c);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(expr.span, "Const::from_anon_const: couldn't lit_to_const");
|
||||
match tcx.at(expr.span).lit_to_const(lit_input) {
|
||||
Ok(c) => return Some(c),
|
||||
Err(e) => {
|
||||
tcx.sess.delay_span_bug(
|
||||
expr.span,
|
||||
&format!("Const::from_anon_const: couldn't lit_to_const {:?}", e),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,7 +245,7 @@ impl FlagComputation {
|
||||
self.add_projection_ty(projection_ty);
|
||||
match term {
|
||||
Term::Ty(ty) => self.add_ty(ty),
|
||||
Term::Const(_c) => todo!(),
|
||||
Term::Const(c) => self.add_const(c),
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::WellFormed(arg) => {
|
||||
|
@ -815,8 +815,8 @@ impl<'tcx> From<&'tcx Const<'tcx>> for Term<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> Term<'tcx> {
|
||||
pub fn ty(&self) -> Ty<'tcx> {
|
||||
if let Term::Ty(ty) = self { ty } else { panic!("Expected type") }
|
||||
pub fn ty(&self) -> Option<Ty<'tcx>> {
|
||||
if let Term::Ty(ty) = self { Some(ty) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
@ -861,8 +861,8 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
|
||||
self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx))
|
||||
}
|
||||
|
||||
pub fn ty(&self) -> Binder<'tcx, Ty<'tcx>> {
|
||||
self.map_bound(|predicate| if let Term::Ty(ty) = predicate.term { ty } else { todo!() })
|
||||
pub fn term(&self) -> Binder<'tcx, Term<'tcx>> {
|
||||
self.map_bound(|predicate| predicate.term)
|
||||
}
|
||||
|
||||
/// The `DefId` of the `TraitItem` for the associated type.
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Provenance, Scalar};
|
||||
use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
|
||||
use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable};
|
||||
use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sso::SsoHashSet;
|
||||
@ -799,7 +799,7 @@ pub trait PrettyPrinter<'tcx>:
|
||||
let trait_ref = proj_ref.required_poly_trait_ref(self.tcx());
|
||||
|
||||
// Projection type entry -- the def-id for naming, and the ty.
|
||||
let proj_ty = (proj_ref.projection_def_id(), proj_ref.ty());
|
||||
let proj_ty = (proj_ref.projection_def_id(), proj_ref.term());
|
||||
|
||||
self.insert_trait_and_projection(
|
||||
trait_ref,
|
||||
@ -850,8 +850,10 @@ pub trait PrettyPrinter<'tcx>:
|
||||
}
|
||||
|
||||
p!(")");
|
||||
if !return_ty.skip_binder().is_unit() {
|
||||
p!("-> ", print(return_ty));
|
||||
if let Term::Ty(ty) = return_ty.skip_binder() {
|
||||
if !ty.is_unit() {
|
||||
p!("-> ", print(return_ty));
|
||||
}
|
||||
}
|
||||
p!(write("{}", if paren_needed { ")" } else { "" }));
|
||||
|
||||
@ -902,14 +904,15 @@ pub trait PrettyPrinter<'tcx>:
|
||||
first = false;
|
||||
}
|
||||
|
||||
for (assoc_item_def_id, ty) in assoc_items {
|
||||
for (assoc_item_def_id, term) in assoc_items {
|
||||
let ty = if let Term::Ty(ty) = term.skip_binder() { ty } else { continue };
|
||||
if !first {
|
||||
p!(", ");
|
||||
}
|
||||
p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).ident));
|
||||
|
||||
// Skip printing `<[generator@] as Generator<_>>::Return` from async blocks
|
||||
match ty.skip_binder().kind() {
|
||||
match ty.kind() {
|
||||
ty::Projection(ty::ProjectionTy { item_def_id, .. })
|
||||
if Some(*item_def_id) == self.tcx().lang_items().generator_return() =>
|
||||
{
|
||||
@ -943,8 +946,11 @@ pub trait PrettyPrinter<'tcx>:
|
||||
fn insert_trait_and_projection(
|
||||
&mut self,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
proj_ty: Option<(DefId, ty::Binder<'tcx, Ty<'tcx>>)>,
|
||||
traits: &mut BTreeMap<ty::PolyTraitRef<'tcx>, BTreeMap<DefId, ty::Binder<'tcx, Ty<'tcx>>>>,
|
||||
proj_ty: Option<(DefId, ty::Binder<'tcx, Term<'tcx>>)>,
|
||||
traits: &mut BTreeMap<
|
||||
ty::PolyTraitRef<'tcx>,
|
||||
BTreeMap<DefId, ty::Binder<'tcx, Term<'tcx>>>,
|
||||
>,
|
||||
fn_traits: &mut BTreeMap<ty::PolyTraitRef<'tcx>, OpaqueFnEntry<'tcx>>,
|
||||
) {
|
||||
let trait_def_id = trait_ref.def_id();
|
||||
@ -2716,5 +2722,5 @@ pub struct OpaqueFnEntry<'tcx> {
|
||||
has_fn_once: bool,
|
||||
fn_mut_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
|
||||
fn_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
|
||||
return_ty: Option<ty::Binder<'tcx, Ty<'tcx>>>,
|
||||
return_ty: Option<ty::Binder<'tcx, Term<'tcx>>>,
|
||||
}
|
||||
|
@ -833,19 +833,30 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::Term<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: Self,
|
||||
b: Self,
|
||||
) -> RelateResult<'tcx, Self> {
|
||||
Ok(match (a, b) {
|
||||
(Term::Ty(a), Term::Ty(b)) => relation.relate(a, b)?.into(),
|
||||
(Term::Const(a), Term::Const(b)) => relation.relate(a, b)?.into(),
|
||||
_ => return Err(TypeError::Mismatch),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: ty::ProjectionPredicate<'tcx>,
|
||||
b: ty::ProjectionPredicate<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> {
|
||||
match (a.term, b.term) {
|
||||
(Term::Ty(a_ty), Term::Ty(b_ty)) => Ok(ty::ProjectionPredicate {
|
||||
projection_ty: relation.relate(a.projection_ty, b.projection_ty)?,
|
||||
term: relation.relate(a_ty, b_ty)?.into(),
|
||||
}),
|
||||
_ => todo!(),
|
||||
}
|
||||
Ok(ty::ProjectionPredicate {
|
||||
projection_ty: relation.relate(a.projection_ty, b.projection_ty)?,
|
||||
term: relation.relate(a.term, b.term)?.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1583,7 +1583,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
|
||||
let ty = if let Term::Ty(ty) = projection_predicate.term {
|
||||
ty
|
||||
} else {
|
||||
todo!();
|
||||
panic!("Only types are permitted here");
|
||||
};
|
||||
|
||||
Self {
|
||||
|
@ -128,8 +128,10 @@ where
|
||||
polarity: _,
|
||||
}) => self.visit_trait(trait_ref),
|
||||
ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
|
||||
let ty = term.ty();
|
||||
ty.visit_with(self)?;
|
||||
match term {
|
||||
ty::Term::Ty(ty) => ty.visit_with(self)?,
|
||||
ty::Term::Const(ct) => ct.visit_with(self)?,
|
||||
}
|
||||
self.visit_projection_ty(projection_ty)
|
||||
}
|
||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => {
|
||||
@ -1186,10 +1188,13 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||
}
|
||||
|
||||
for (poly_predicate, _) in bounds.projection_bounds {
|
||||
if self.visit(poly_predicate.skip_binder().term.ty()).is_break()
|
||||
|| self
|
||||
.visit_projection_ty(poly_predicate.skip_binder().projection_ty)
|
||||
.is_break()
|
||||
let pred = poly_predicate.skip_binder();
|
||||
let poly_pred_term = match pred.term {
|
||||
ty::Term::Ty(ty) => self.visit(ty),
|
||||
ty::Term::Const(ct) => self.visit(ct),
|
||||
};
|
||||
if poly_pred_term.is_break()
|
||||
|| self.visit_projection_ty(pred.projection_ty).is_break()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use super::*;
|
||||
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
|
||||
use crate::infer::InferCtxt;
|
||||
use rustc_middle::ty::fold::TypeFolder;
|
||||
use rustc_middle::ty::{Region, RegionVid};
|
||||
use rustc_middle::ty::{Region, RegionVid, Term};
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
|
||||
@ -606,7 +606,11 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||
}
|
||||
|
||||
fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
|
||||
matches!(*p.ty().skip_binder().kind(), ty::Projection(proj) if proj == p.skip_binder().projection_ty)
|
||||
if let Term::Ty(ty) = p.term().skip_binder() {
|
||||
matches!(ty.kind(), ty::Projection(proj) if proj == &p.skip_binder().projection_ty)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn evaluate_nested_obligations(
|
||||
@ -663,7 +667,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||
// Additionally, we check if we've seen this predicate before,
|
||||
// to avoid rendering duplicate bounds to the user.
|
||||
if self.is_param_no_infer(p.skip_binder().projection_ty.substs)
|
||||
&& !p.ty().skip_binder().has_infer_types()
|
||||
&& !p.term().skip_binder().has_infer_types()
|
||||
&& is_new_pred
|
||||
{
|
||||
debug!(
|
||||
@ -752,7 +756,8 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||
// when we started out trying to unify
|
||||
// some inference variables. See the comment above
|
||||
// for more infomration
|
||||
if p.ty().skip_binder().has_infer_types() {
|
||||
if p.term().skip_binder().ty().map_or(false, |ty| ty.has_infer_types())
|
||||
{
|
||||
if !self.evaluate_nested_obligations(
|
||||
ty,
|
||||
v.into_iter(),
|
||||
@ -774,7 +779,8 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||
// However, we should always make progress (either by generating
|
||||
// subobligations or getting an error) when we started off with
|
||||
// inference variables
|
||||
if p.ty().skip_binder().has_infer_types() {
|
||||
if p.term().skip_binder().ty().map_or(false, |ty| ty.has_infer_types())
|
||||
{
|
||||
panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
|
||||
}
|
||||
}
|
||||
|
@ -1304,8 +1304,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||
|
||||
debug!(
|
||||
"report_projection_error normalized_ty={:?} data.ty={:?}",
|
||||
normalized_ty,
|
||||
data.term.ty()
|
||||
normalized_ty, data.term,
|
||||
);
|
||||
|
||||
let is_normalized_ty_expected = !matches!(
|
||||
@ -1315,16 +1314,17 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||
| ObligationCauseCode::ObjectCastObligation(_)
|
||||
| ObligationCauseCode::OpaqueType
|
||||
);
|
||||
|
||||
// FIXME(...): Handle Consts here
|
||||
let data_ty = data.term.ty().unwrap();
|
||||
if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
|
||||
is_normalized_ty_expected,
|
||||
normalized_ty,
|
||||
data.term.ty(),
|
||||
data_ty,
|
||||
) {
|
||||
values = Some(infer::ValuePairs::Types(ExpectedFound::new(
|
||||
is_normalized_ty_expected,
|
||||
normalized_ty,
|
||||
data.term.ty(),
|
||||
data_ty,
|
||||
)));
|
||||
|
||||
err_buf = error;
|
||||
|
@ -212,10 +212,9 @@ fn project_and_unify_type<'cx, 'tcx>(
|
||||
debug!(?normalized_ty, ?obligations, "project_and_unify_type result");
|
||||
|
||||
let infcx = selcx.infcx();
|
||||
match infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.eq(normalized_ty, obligation.predicate.term.ty())
|
||||
{
|
||||
// FIXME(...): Handle consts here as well as types.
|
||||
let obligation_pred_ty = obligation.predicate.term.ty().unwrap();
|
||||
match infcx.at(&obligation.cause, obligation.param_env).eq(normalized_ty, obligation_pred_ty) {
|
||||
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
|
||||
obligations.extend(inferred_obligations);
|
||||
Ok(Ok(Some(obligations)))
|
||||
@ -1803,7 +1802,9 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
|
||||
Ok(InferOk { value: _, obligations }) => {
|
||||
nested_obligations.extend(obligations);
|
||||
assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations);
|
||||
Progress { ty: cache_entry.term.ty(), obligations: nested_obligations }
|
||||
// FIXME(...): Handle consts here as well? Maybe this progress type should just take
|
||||
// a term instead.
|
||||
Progress { ty: cache_entry.term.ty().unwrap(), obligations: nested_obligations }
|
||||
}
|
||||
Err(e) => {
|
||||
let msg = format!(
|
||||
|
@ -62,7 +62,7 @@ pub(crate) fn update<'tcx, T>(
|
||||
if let ty::PredicateKind::Projection(predicate) = obligation.predicate.kind().skip_binder() {
|
||||
// If the projection predicate (Foo::Bar == X) has X as a non-TyVid,
|
||||
// we need to make it into one.
|
||||
if let Some(vid) = predicate.term.ty().ty_vid() {
|
||||
if let Some(vid) = predicate.term.ty().and_then(|ty| ty.ty_vid()) {
|
||||
debug!("relationship: {:?}.output = true", vid);
|
||||
engine.relationships().entry(vid).or_default().output = true;
|
||||
}
|
||||
|
@ -116,7 +116,10 @@ pub fn predicate_obligations<'a, 'tcx>(
|
||||
}
|
||||
ty::PredicateKind::Projection(t) => {
|
||||
wf.compute_projection(t.projection_ty);
|
||||
wf.compute(t.term.ty().into());
|
||||
wf.compute(match t.term {
|
||||
ty::Term::Ty(ty) => ty.into(),
|
||||
ty::Term::Const(c) => c.into(),
|
||||
})
|
||||
}
|
||||
ty::PredicateKind::WellFormed(arg) => {
|
||||
wf.compute(arg);
|
||||
@ -219,7 +222,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
|
||||
// projection coming from another associated type. See
|
||||
// `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
|
||||
// `traits-assoc-type-in-supertrait-bad.rs`.
|
||||
if let ty::Projection(projection_ty) = proj.term.ty().kind() {
|
||||
if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind()) {
|
||||
if let Some(&impl_item_id) =
|
||||
tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
|
||||
{
|
||||
|
@ -227,12 +227,24 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq<RustInterner<'tcx>>>
|
||||
{
|
||||
fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq<RustInterner<'tcx>> {
|
||||
chalk_ir::AliasEq {
|
||||
ty: self.term.ty().lower_into(interner),
|
||||
ty: self.term.ty().unwrap().lower_into(interner),
|
||||
alias: self.projection_ty.lower_into(interner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// FIXME(...): Where do I add this to Chalk? I can't find it in the rustc repo anywhere.
|
||||
impl<'tcx> LowerInto<'tcx, chalk_ir::Term<RustInterner<'tcx>>> for rustc_middle::ty::Term<'tcx> {
|
||||
fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Term<RustInterner<'tcx>> {
|
||||
match self {
|
||||
ty::Term::Ty(ty) => ty.lower_into(interner).into(),
|
||||
ty::Term::Const(c) => c.lower_into(interner).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> {
|
||||
fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Ty<RustInterner<'tcx>> {
|
||||
let int = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(i));
|
||||
@ -787,7 +799,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>
|
||||
trait_bound: trait_ref.lower_into(interner),
|
||||
associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id),
|
||||
parameters: own_substs.iter().map(|arg| arg.lower_into(interner)).collect(),
|
||||
value: self.term.ty().lower_into(interner),
|
||||
value: self.term.ty().unwrap().lower_into(interner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,8 +123,7 @@ struct ConvertedBinding<'a, 'tcx> {
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ConvertedBindingKind<'a, 'tcx> {
|
||||
Equality(Ty<'tcx>),
|
||||
Const(&'tcx Const<'tcx>),
|
||||
Equality(ty::Term<'tcx>),
|
||||
Constraint(&'a [hir::GenericBound<'a>]),
|
||||
}
|
||||
|
||||
@ -604,12 +603,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
let kind = match binding.kind {
|
||||
hir::TypeBindingKind::Equality { ref term } => match term {
|
||||
hir::Term::Ty(ref ty) => {
|
||||
ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty))
|
||||
ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty).into())
|
||||
}
|
||||
hir::Term::Const(ref c) => {
|
||||
let local_did = self.tcx().hir().local_def_id(c.hir_id);
|
||||
let c = Const::from_anon_const(self.tcx(), local_did);
|
||||
ConvertedBindingKind::Const(&c)
|
||||
ConvertedBindingKind::Equality(c.into())
|
||||
}
|
||||
},
|
||||
hir::TypeBindingKind::Constraint { ref bounds } => {
|
||||
@ -875,6 +874,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
.find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id)
|
||||
.is_some()
|
||||
}
|
||||
fn trait_defines_associated_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
|
||||
self.tcx()
|
||||
.associated_items(trait_def_id)
|
||||
.find_by_name_and_kinds(
|
||||
self.tcx(),
|
||||
assoc_name,
|
||||
&[ty::AssocKind::Type, ty::AssocKind::Const],
|
||||
trait_def_id,
|
||||
)
|
||||
.is_some()
|
||||
}
|
||||
|
||||
// Sets `implicitly_sized` to true on `Bounds` if necessary
|
||||
pub(crate) fn add_implicitly_sized<'hir>(
|
||||
@ -1223,7 +1233,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
}
|
||||
|
||||
match binding.kind {
|
||||
ConvertedBindingKind::Equality(ty) => {
|
||||
ConvertedBindingKind::Equality(term) => {
|
||||
// "Desugar" a constraint like `T: Iterator<Item = u32>` this to
|
||||
// the "projection predicate" for:
|
||||
//
|
||||
@ -1231,16 +1241,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
bounds.projection_bounds.push((
|
||||
projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate {
|
||||
projection_ty,
|
||||
term: ty.into(),
|
||||
}),
|
||||
binding.span,
|
||||
));
|
||||
}
|
||||
ConvertedBindingKind::Const(c) => {
|
||||
bounds.projection_bounds.push((
|
||||
projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate {
|
||||
projection_ty,
|
||||
term: c.into(),
|
||||
term: term,
|
||||
}),
|
||||
binding.span,
|
||||
));
|
||||
@ -1391,8 +1392,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
let pred = bound_predicate.rebind(pred);
|
||||
// A `Self` within the original bound will be substituted with a
|
||||
// `trait_object_dummy_self`, so check for that.
|
||||
let references_self =
|
||||
pred.skip_binder().term.ty().walk().any(|arg| arg == dummy_self.into());
|
||||
let references_self = match pred.skip_binder().term {
|
||||
ty::Term::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
|
||||
ty::Term::Const(c) => {
|
||||
c.ty.walk().any(|arg| arg == dummy_self.into())
|
||||
}
|
||||
};
|
||||
|
||||
// If the projection output contains `Self`, force the user to
|
||||
// elaborate it explicitly to avoid a lot of complexity.
|
||||
@ -1615,7 +1620,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
||||
{
|
||||
let mut matching_candidates = all_candidates()
|
||||
.filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
|
||||
.filter(|r| self.trait_defines_associated_named(r.def_id(), assoc_name));
|
||||
|
||||
let bound = match matching_candidates.next() {
|
||||
Some(bound) => bound,
|
||||
|
@ -279,7 +279,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return None;
|
||||
};
|
||||
|
||||
let ret_param_ty = projection.skip_binder().term.ty();
|
||||
// Since this is a return parameter type it is safe to unwrap.
|
||||
let ret_param_ty = projection.skip_binder().term.ty().unwrap();
|
||||
let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty);
|
||||
debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty);
|
||||
|
||||
@ -706,9 +707,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// Extract the type from the projection. Note that there can
|
||||
// be no bound variables in this type because the "self type"
|
||||
// does not have any regions in it.
|
||||
let output_ty = self.resolve_vars_if_possible(predicate.term.ty());
|
||||
let output_ty = self.resolve_vars_if_possible(predicate.term);
|
||||
debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty);
|
||||
Some(output_ty)
|
||||
// FIXME(...): How to handle consts here? Will this always be a const?
|
||||
Some(output_ty.ty().unwrap())
|
||||
}
|
||||
|
||||
/// Converts the types that the user supplied, in case that doing
|
||||
|
@ -789,10 +789,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
item_def_id: projection_ty.item_def_id,
|
||||
};
|
||||
|
||||
let ty: Ty<'_> = pred.skip_binder().term.ty();
|
||||
let fmt = match pred.skip_binder().term {
|
||||
ty::Term::Ty(ty) => format!("{}", ty),
|
||||
ty::Term::Const(c) => format!("{}", c),
|
||||
};
|
||||
|
||||
let obligation = format!("{} = {}", projection_ty, ty);
|
||||
let quiet = format!("{} = {}", quiet_projection_ty, ty);
|
||||
let obligation = format!("{} = {}", projection_ty, fmt);
|
||||
let quiet = format!("{} = {}", quiet_projection_ty, fmt);
|
||||
|
||||
bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
|
||||
Some((obligation, projection_ty.self_ty()))
|
||||
|
@ -694,7 +694,10 @@ fn bounds_from_generic_predicates<'tcx>(
|
||||
where_clauses.push(format!(
|
||||
"{} = {}",
|
||||
tcx.def_path_str(p.projection_ty.item_def_id),
|
||||
p.term.ty()
|
||||
match p.term {
|
||||
ty::Term::Ty(ty) => format!("{}", ty),
|
||||
ty::Term::Const(c) => format!("{}", c),
|
||||
}
|
||||
));
|
||||
}
|
||||
let where_clauses = if where_clauses.is_empty() {
|
||||
|
@ -553,8 +553,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
if self.is_fn_trait(trait_) && left_name == sym::Output {
|
||||
ty_to_fn
|
||||
.entry(*ty.clone())
|
||||
.and_modify(|e| *e = (e.0.clone(), Some(rhs.clone())))
|
||||
.or_insert((None, Some(rhs)));
|
||||
.and_modify(|e| {
|
||||
*e = (e.0.clone(), Some(rhs.ty().unwrap().clone()))
|
||||
})
|
||||
.or_insert((None, Some(rhs.ty().unwrap().clone())));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -570,7 +572,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
GenericArgs::AngleBracketed { ref mut bindings, .. } => {
|
||||
bindings.push(TypeBinding {
|
||||
name: left_name,
|
||||
kind: TypeBindingKind::Equality { ty: rhs },
|
||||
kind: TypeBindingKind::Equality { term: rhs },
|
||||
});
|
||||
}
|
||||
GenericArgs::Parenthesized { .. } => {
|
||||
|
@ -272,9 +272,10 @@ impl Clean<WherePredicate> for hir::WherePredicate<'_> {
|
||||
bounds: wrp.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
|
||||
},
|
||||
|
||||
hir::WherePredicate::EqPredicate(ref wrp) => {
|
||||
WherePredicate::EqPredicate { lhs: wrp.lhs_ty.clean(cx), rhs: wrp.rhs_ty.clean(cx) }
|
||||
}
|
||||
hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
|
||||
lhs: wrp.lhs_ty.clean(cx),
|
||||
rhs: wrp.rhs_ty.clean(cx).into(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -352,11 +353,31 @@ impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty:
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Term> for ty::Term<'tcx> {
|
||||
fn clean(&self, cx: &mut DocContext<'_>) -> Term {
|
||||
match self {
|
||||
ty::Term::Ty(ty) => Term::Type(ty.clean(cx)),
|
||||
ty::Term::Const(c) => Term::Constant(c.clean(cx)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Term> for hir::Term<'tcx> {
|
||||
fn clean(&self, cx: &mut DocContext<'_>) -> Term {
|
||||
match self {
|
||||
hir::Term::Ty(ty) => Term::Type(ty.clean(cx)),
|
||||
hir::Term::Const(c) => {
|
||||
let def_id = cx.tcx.hir().local_def_id(c.hir_id);
|
||||
Term::Constant(ty::Const::from_anon_const(cx.tcx, def_id).clean(cx))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
|
||||
fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
|
||||
let ty::ProjectionPredicate { projection_ty, term } = self;
|
||||
let ty = term.ty();
|
||||
WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) }
|
||||
WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: term.clean(cx) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -614,7 +635,7 @@ fn clean_ty_generics(
|
||||
|
||||
if let Some(param_idx) = param_idx {
|
||||
if let Some(b) = impl_trait.get_mut(¶m_idx.into()) {
|
||||
let p = p.clean(cx)?;
|
||||
let p: WherePredicate = p.clean(cx)?;
|
||||
|
||||
b.extend(
|
||||
p.get_bounds()
|
||||
@ -624,13 +645,17 @@ fn clean_ty_generics(
|
||||
.filter(|b| !b.is_sized_bound(cx)),
|
||||
);
|
||||
|
||||
let proj = projection.map(|p| {
|
||||
(p.skip_binder().projection_ty.clean(cx), p.skip_binder().term.ty())
|
||||
});
|
||||
let proj = projection
|
||||
.map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().term));
|
||||
if let Some(((_, trait_did, name), rhs)) =
|
||||
proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
|
||||
{
|
||||
impl_trait_proj.entry(param_idx).or_default().push((trait_did, name, rhs));
|
||||
// FIXME(...): Remove this unwrap()
|
||||
impl_trait_proj.entry(param_idx).or_default().push((
|
||||
trait_did,
|
||||
name,
|
||||
rhs.ty().unwrap(),
|
||||
));
|
||||
}
|
||||
|
||||
return None;
|
||||
@ -649,7 +674,7 @@ fn clean_ty_generics(
|
||||
if let Some(proj) = impl_trait_proj.remove(&idx) {
|
||||
for (trait_did, name, rhs) in proj {
|
||||
let rhs = rhs.clean(cx);
|
||||
simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs);
|
||||
simplify::merge_bounds(cx, &mut bounds, trait_did, name, &Term::Type(rhs));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1497,7 +1522,9 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||
for pb in obj.projection_bounds() {
|
||||
bindings.push(TypeBinding {
|
||||
name: cx.tcx.associated_item(pb.item_def_id()).ident.name,
|
||||
kind: TypeBindingKind::Equality { ty: pb.skip_binder().ty.clean(cx) },
|
||||
kind: TypeBindingKind::Equality {
|
||||
term: pb.skip_binder().ty.clean(cx).into(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -1568,7 +1595,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||
.ident
|
||||
.name,
|
||||
kind: TypeBindingKind::Equality {
|
||||
ty: proj.term.ty().clean(cx),
|
||||
term: proj.term.clean(cx),
|
||||
},
|
||||
})
|
||||
} else {
|
||||
@ -2116,10 +2143,9 @@ impl Clean<TypeBinding> for hir::TypeBinding<'_> {
|
||||
impl Clean<TypeBindingKind> for hir::TypeBindingKind<'_> {
|
||||
fn clean(&self, cx: &mut DocContext<'_>) -> TypeBindingKind {
|
||||
match *self {
|
||||
hir::TypeBindingKind::Equality { ref term } => match term {
|
||||
hir::Term::Ty(ref ty) => TypeBindingKind::Equality { ty: ty.clean(cx) },
|
||||
hir::Term::Const(ref _c) => todo!(),
|
||||
},
|
||||
hir::TypeBindingKind::Equality { ref term } => {
|
||||
TypeBindingKind::Equality { term: term.clean(cx) }
|
||||
}
|
||||
hir::TypeBindingKind::Constraint { ref bounds } => TypeBindingKind::Constraint {
|
||||
bounds: bounds.iter().filter_map(|b| b.clean(cx)).collect(),
|
||||
},
|
||||
|
@ -92,7 +92,7 @@ crate fn merge_bounds(
|
||||
bounds: &mut Vec<clean::GenericBound>,
|
||||
trait_did: DefId,
|
||||
name: Symbol,
|
||||
rhs: &clean::Type,
|
||||
rhs: &clean::Term,
|
||||
) -> bool {
|
||||
!bounds.iter_mut().any(|b| {
|
||||
let trait_ref = match *b {
|
||||
@ -110,14 +110,14 @@ crate fn merge_bounds(
|
||||
PP::AngleBracketed { ref mut bindings, .. } => {
|
||||
bindings.push(clean::TypeBinding {
|
||||
name,
|
||||
kind: clean::TypeBindingKind::Equality { ty: rhs.clone() },
|
||||
kind: clean::TypeBindingKind::Equality { term: rhs.clone() },
|
||||
});
|
||||
}
|
||||
PP::Parenthesized { ref mut output, .. } => match output {
|
||||
Some(o) => assert_eq!(o.as_ref(), rhs),
|
||||
Some(o) => assert_eq!(&clean::Term::Type(o.as_ref().clone()), rhs),
|
||||
None => {
|
||||
if *rhs != clean::Type::Tuple(Vec::new()) {
|
||||
*output = Some(Box::new(rhs.clone()));
|
||||
if *rhs != clean::Term::Type(clean::Type::Tuple(Vec::new())) {
|
||||
*output = Some(Box::new(rhs.ty().unwrap().clone()));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1212,7 +1212,7 @@ impl Lifetime {
|
||||
crate enum WherePredicate {
|
||||
BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
|
||||
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
|
||||
EqPredicate { lhs: Type, rhs: Type },
|
||||
EqPredicate { lhs: Type, rhs: Term },
|
||||
}
|
||||
|
||||
impl WherePredicate {
|
||||
@ -1308,7 +1308,12 @@ impl FnDecl {
|
||||
FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
|
||||
GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
|
||||
let bindings = trait_.bindings().unwrap();
|
||||
FnRetTy::Return(bindings[0].ty().clone())
|
||||
let ret_ty = bindings[0].term();
|
||||
let ty = match ret_ty {
|
||||
Term::Type(ty) => ty,
|
||||
Term::Constant(_c) => unreachable!(),
|
||||
};
|
||||
FnRetTy::Return(ty.clone())
|
||||
}
|
||||
_ => panic!("unexpected desugaring of async function"),
|
||||
},
|
||||
@ -2121,6 +2126,24 @@ crate struct Constant {
|
||||
crate kind: ConstantKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
crate enum Term {
|
||||
Type(Type),
|
||||
Constant(Constant),
|
||||
}
|
||||
|
||||
impl Term {
|
||||
crate fn ty(&self) -> Option<&Type> {
|
||||
if let Term::Type(ty) = self { Some(ty) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Type> for Term {
|
||||
fn from(ty: Type) -> Self {
|
||||
Term::Type(ty)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
crate enum ConstantKind {
|
||||
/// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
|
||||
@ -2283,14 +2306,14 @@ crate struct TypeBinding {
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
crate enum TypeBindingKind {
|
||||
Equality { ty: Type },
|
||||
Equality { term: Term },
|
||||
Constraint { bounds: Vec<GenericBound> },
|
||||
}
|
||||
|
||||
impl TypeBinding {
|
||||
crate fn ty(&self) -> &Type {
|
||||
crate fn term(&self) -> &Term {
|
||||
match self.kind {
|
||||
TypeBindingKind::Equality { ref ty } => ty,
|
||||
TypeBindingKind::Equality { ref term } => term,
|
||||
_ => panic!("expected equality type binding for parenthesized generic args"),
|
||||
}
|
||||
}
|
||||
|
@ -1442,11 +1442,11 @@ impl clean::TypeBinding {
|
||||
display_fn(move |f| {
|
||||
f.write_str(self.name.as_str())?;
|
||||
match self.kind {
|
||||
clean::TypeBindingKind::Equality { ref ty } => {
|
||||
clean::TypeBindingKind::Equality { ref term } => {
|
||||
if f.alternate() {
|
||||
write!(f, " = {:#}", ty.print(cx))?;
|
||||
write!(f, " = {:#}", term.print(cx))?;
|
||||
} else {
|
||||
write!(f, " = {}", ty.print(cx))?;
|
||||
write!(f, " = {}", term.print(cx))?;
|
||||
}
|
||||
}
|
||||
clean::TypeBindingKind::Constraint { ref bounds } => {
|
||||
@ -1492,6 +1492,18 @@ impl clean::GenericArg {
|
||||
}
|
||||
}
|
||||
|
||||
impl clean::types::Term {
|
||||
crate fn print<'a, 'tcx: 'a>(
|
||||
&'a self,
|
||||
cx: &'a Context<'tcx>,
|
||||
) -> impl fmt::Display + 'a + Captures<'tcx> {
|
||||
match self {
|
||||
clean::types::Term::Type(ty) => ty.print(cx),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crate fn display_fn(f: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Display {
|
||||
struct WithFormatter<F>(Cell<Option<F>>);
|
||||
|
||||
|
@ -162,7 +162,7 @@ impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
|
||||
fn from_tcx(kind: clean::TypeBindingKind, tcx: TyCtxt<'_>) -> Self {
|
||||
use clean::TypeBindingKind::*;
|
||||
match kind {
|
||||
Equality { ty } => TypeBindingKind::Equality(ty.into_tcx(tcx)),
|
||||
Equality { term } => TypeBindingKind::Equality(term.into_tcx(tcx)),
|
||||
Constraint { bounds } => {
|
||||
TypeBindingKind::Constraint(bounds.into_iter().map(|a| a.into_tcx(tcx)).collect())
|
||||
}
|
||||
@ -452,6 +452,15 @@ impl FromWithTcx<clean::Type> for Type {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromWithTcx<clean::Term> for Term {
|
||||
fn from_tcx(term: clean::Term, tcx: TyCtxt<'_>) -> Term {
|
||||
match term {
|
||||
clean::Term::Type(ty) => Term::Type(FromWithTcx::from_tcx(ty, tcx)),
|
||||
clean::Term::Constant(c) => Term::Constant(FromWithTcx::from_tcx(c, tcx)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromWithTcx<clean::BareFunctionDecl> for FunctionPointer {
|
||||
fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self {
|
||||
let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl;
|
||||
|
@ -148,7 +148,7 @@ pub struct TypeBinding {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum TypeBindingKind {
|
||||
Equality(Type),
|
||||
Equality(Term),
|
||||
Constraint(Vec<GenericBound>),
|
||||
}
|
||||
|
||||
@ -335,7 +335,7 @@ pub enum GenericParamDefKind {
|
||||
pub enum WherePredicate {
|
||||
BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
|
||||
RegionPredicate { lifetime: String, bounds: Vec<GenericBound> },
|
||||
EqPredicate { lhs: Type, rhs: Type },
|
||||
EqPredicate { lhs: Type, rhs: Term },
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
@ -359,6 +359,13 @@ pub enum TraitBoundModifier {
|
||||
MaybeConst,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Term {
|
||||
Type(Type),
|
||||
Constant(Constant),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[serde(tag = "kind", content = "inner")]
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[HASH]::Id::This) }, (I,)), [])`
|
||||
error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[HASH]::Id::This) }, Ty((I,))), [])`
|
||||
--> $DIR/repeated_projection_type.rs:19:1
|
||||
|
|
||||
LL | / impl<I, V: Id<This = (I,)>> X for V {
|
||||
|
@ -2141,12 +2141,16 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
|
||||
// one of the associated types must be Self
|
||||
for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
|
||||
if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
|
||||
let assoc_ty = match projection_predicate.term {
|
||||
ty::Term::Ty(ty) => ty,
|
||||
ty::Term::Const(c) => c.ty,
|
||||
};
|
||||
// walk the associated type and check for Self
|
||||
if let Some(self_adt) = self_ty.ty_adt_def() {
|
||||
if contains_adt_constructor(projection_predicate.term.ty(), self_adt) {
|
||||
if contains_adt_constructor(assoc_ty, self_adt) {
|
||||
return;
|
||||
}
|
||||
} else if contains_ty(projection_predicate.term.ty(), self_ty) {
|
||||
} else if contains_ty(assoc_ty, self_ty) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -243,9 +243,10 @@ fn check_other_call_arg<'tcx>(
|
||||
if if trait_predicate.def_id() == deref_trait_id {
|
||||
if let [projection_predicate] = projection_predicates[..] {
|
||||
let normalized_ty =
|
||||
cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.term.ty());
|
||||
cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.term);
|
||||
implements_trait(cx, receiver_ty, deref_trait_id, &[])
|
||||
&& get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(normalized_ty)
|
||||
&& get_associated_type(cx, receiver_ty, deref_trait_id,
|
||||
"Target").map_or(false, |ty| ty::Term::Ty(ty) == normalized_ty)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -98,9 +98,10 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
|
||||
if trait_pred.self_ty() == inp;
|
||||
if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred);
|
||||
then {
|
||||
if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.term.ty()) {
|
||||
if ord_preds.iter().any(|ord| Some(ord.self_ty()) ==
|
||||
return_ty_pred.term.ty()) {
|
||||
args_to_check.push((i, "Ord".to_string()));
|
||||
} else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.term.ty()) {
|
||||
} else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.term.ty().unwrap()) {
|
||||
args_to_check.push((i, "PartialOrd".to_string()));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user