diff options
| author | kadmin <julianknodt@gmail.com> | 2022-01-10 23:39:21 +0000 |
|---|---|---|
| committer | kadmin <julianknodt@gmail.com> | 2022-01-17 19:59:40 +0000 |
| commit | e7529d6a3867ed1692818702b40814ee992eba2d (patch) | |
| tree | 604113f2d4e343f78db6c168ce8624a767de87d7 | |
| parent | 67f56671d0384bdb2d92dddebfbf42510b16e0f7 (diff) | |
| download | rust-e7529d6a3867ed1692818702b40814ee992eba2d.tar.gz rust-e7529d6a3867ed1692818702b40814ee992eba2d.zip | |
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.
31 files changed, 284 insertions, 128 deletions
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 39339da9a0b..4851e637d3a 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -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(); } } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 0d1081ee26b..3921187baa5 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -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, } } diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 8563bac0bbf..2776370ba6f 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -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, diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 75705d40a6c..d6c35dfef88 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -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), + ); + } } } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 74c8d7b7777..be9021dc619 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -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) => { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f1851150e38..42e6f3f6ef5 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 8c07f154637..6fcb6ac5f4c 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -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>>>, } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 851c4592f4f..bd6c24445ef 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -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(), + }) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 50d0862905b..453e380f6e3 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -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 { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index dc432905b1c..73873c8cf0d 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -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; } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 05d2a373dc6..cc20c117945 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -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) } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 85135383b80..43a961c5c91 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -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; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 4995590baec..4b53b624c72 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -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!( diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs index acac76cdfaa..aea44841b8f 100644 --- a/compiler/rustc_trait_selection/src/traits/relationships.rs +++ b/compiler/rustc_trait_selection/src/traits/relationships.rs @@ -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; } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index e3b366c65bf..6a355b567e0 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -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) { diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index e651ff63c52..dd98e4ae81b 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -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), } } } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 2866a7884a7..a13eaa6f178 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -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, diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index c8e1d8b190c..504807e87b6 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -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 diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 590d65b7cba..bf362357ed0 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -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())) diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 8d06b8a7a17..9f67713d585 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -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() { diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 09692d27e8f..18a4d8a4753 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -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 { .. } => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f6af81769b7..6a3cdcc2c20 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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(), }, diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 4c81e75e8d6..0bad1532808 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -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())); } } }, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 00c6e38839f..ba771c0c1a1 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -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"), }, @@ -2122,6 +2127,24 @@ crate struct Constant { } #[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 /// `BodyId`, we need to handle it on its own. @@ -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"), } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 8571a6a137f..08840626259 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -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>>); diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index c8efa4bbbcc..e77bd5c9223 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -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; diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 9466f84ffcd..618c8aab86a 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -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)] @@ -361,6 +361,13 @@ pub enum TraitBoundModifier { #[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")] pub enum Type { /// Structs, enums, and traits diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr index 07d194476a5..ad51707070f 100644 --- a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr +++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr @@ -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 { diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index c0e65e520f2..ca8bbbd8f91 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -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; } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 865a36a5cd1..9162de3ccea 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -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 } diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs index 09f9e1ee099..68156df2ece 100644 --- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs +++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs @@ -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())); } } |
