From 626abc797704009e4683be5d95dbeb9417999c82 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 23 Mar 2020 06:04:03 +0200 Subject: [PATCH] ty: remove `{Existential,}Trait{Ref,Predicate}::input_types`. --- src/librustc_middle/ty/mod.rs | 4 - src/librustc_middle/ty/sty.rs | 16 --- .../traits/coherence.rs | 10 +- .../traits/object_safety.rs | 14 +-- src/librustc_trait_selection/traits/select.rs | 38 +++++-- src/librustc_typeck/check/coercion.rs | 24 ++-- src/librustdoc/clean/mod.rs | 104 +++++++++--------- 7 files changed, 103 insertions(+), 107 deletions(-) diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 48bc90526af24..1870856150f50 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -1365,10 +1365,6 @@ impl<'tcx> TraitPredicate<'tcx> { self.trait_ref.def_id } - pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { - self.trait_ref.input_types() - } - pub fn self_ty(&self) -> Ty<'tcx> { self.trait_ref.self_ty() } diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index acbfdbafa17e8..f09327886872c 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -754,14 +754,6 @@ impl<'tcx> TraitRef<'tcx> { self.substs.type_at(0) } - pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { - // Select only the "input types" from a trait-reference. For - // now this is all the types that appear in the - // trait-reference, but it should eventually exclude - // associated types. - self.substs.types() - } - pub fn from_method( tcx: TyCtxt<'tcx>, trait_id: DefId, @@ -805,14 +797,6 @@ pub struct ExistentialTraitRef<'tcx> { } impl<'tcx> ExistentialTraitRef<'tcx> { - pub fn input_types<'b>(&'b self) -> impl DoubleEndedIterator> + 'b { - // Select only the "input types" from a trait-reference. For - // now this is all the types that appear in the - // trait-reference, but it should eventually exclude - // associated types. - self.substs.types() - } - pub fn erase_self_ty( tcx: TyCtxt<'tcx>, trait_ref: ty::TraitRef<'tcx>, diff --git a/src/librustc_trait_selection/traits/coherence.rs b/src/librustc_trait_selection/traits/coherence.rs index 4a71585ec1c10..f1311382c5447 100644 --- a/src/librustc_trait_selection/traits/coherence.rs +++ b/src/librustc_trait_selection/traits/coherence.rs @@ -393,8 +393,11 @@ fn orphan_check_trait_ref<'tcx>( } let mut non_local_spans = vec![]; - for (i, input_ty) in - trait_ref.input_types().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)).enumerate() + for (i, input_ty) in trait_ref + .substs + .types() + .flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)) + .enumerate() { debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty); let non_local_tys = ty_is_non_local(tcx, input_ty, in_crate); @@ -404,7 +407,8 @@ fn orphan_check_trait_ref<'tcx>( } else if let ty::Param(_) = input_ty.kind { debug!("orphan_check_trait_ref: uncovered ty: `{:?}`", input_ty); let local_type = trait_ref - .input_types() + .substs + .types() .flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)) .find(|ty| ty_is_non_local_constructor(ty, in_crate).is_none()); diff --git a/src/librustc_trait_selection/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs index fc2e984e34dd8..d9a5b68dc1eb9 100644 --- a/src/librustc_trait_selection/traits/object_safety.rs +++ b/src/librustc_trait_selection/traits/object_safety.rs @@ -16,7 +16,7 @@ use crate::traits::{self, Obligation, ObligationCause}; use rustc_errors::{Applicability, FatalError}; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_span::symbol::Symbol; @@ -234,7 +234,7 @@ fn predicates_reference_self( tcx.predicates_of(trait_def_id) }; let self_ty = tcx.types.self_param; - let has_self_ty = |t: Ty<'_>| t.walk().any(|arg| arg == self_ty.into()); + let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into()); predicates .predicates .iter() @@ -243,7 +243,7 @@ fn predicates_reference_self( match predicate { ty::Predicate::Trait(ref data, _) => { // In the case of a trait predicate, we can skip the "self" type. - if data.skip_binder().input_types().skip(1).any(has_self_ty) { + if data.skip_binder().trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None @@ -262,12 +262,8 @@ fn predicates_reference_self( // // This is ALT2 in issue #56288, see that for discussion of the // possible alternatives. - if data - .skip_binder() - .projection_ty - .trait_ref(tcx) - .input_types() - .skip(1) + if data.skip_binder().projection_ty.trait_ref(tcx).substs[1..] + .iter() .any(has_self_ty) { Some(sp) diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs index ed547cac5828f..84c264f06db28 100644 --- a/src/librustc_trait_selection/traits/select.rs +++ b/src/librustc_trait_selection/traits/select.rs @@ -652,7 +652,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, stack: &TraitObligationStack<'o, 'tcx>, ) -> Result { - // In intercrate mode, whenever any of the types are unbound, + // In intercrate mode, whenever any of the generics are unbound, // there can always be an impl. Even if there are no impls in // this crate, perhaps the type would be unified with // something from another crate that does provide an impl. @@ -677,7 +677,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // terms of `Fn` etc, but we could probably make this more // precise still. let unbound_input_types = - stack.fresh_trait_ref.skip_binder().input_types().any(|ty| ty.is_fresh()); + stack.fresh_trait_ref.skip_binder().substs.types().any(|ty| ty.is_fresh()); // This check was an imperfect workaround for a bug in the old // intercrate mode; it should be removed when that goes away. if unbound_input_types && self.intercrate { @@ -3262,15 +3262,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // substitution if we find that any of the input types, when // simplified, do not match. - obligation.predicate.skip_binder().input_types().zip(impl_trait_ref.input_types()).any( - |(obligation_ty, impl_ty)| { - let simplified_obligation_ty = - fast_reject::simplify_type(self.tcx(), obligation_ty, true); - let simplified_impl_ty = fast_reject::simplify_type(self.tcx(), impl_ty, false); - - simplified_obligation_ty.is_some() - && simplified_impl_ty.is_some() - && simplified_obligation_ty != simplified_impl_ty + obligation.predicate.skip_binder().trait_ref.substs.iter().zip(impl_trait_ref.substs).any( + |(obligation_arg, impl_arg)| { + match (obligation_arg.unpack(), impl_arg.unpack()) { + (GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => { + let simplified_obligation_ty = + fast_reject::simplify_type(self.tcx(), obligation_ty, true); + let simplified_impl_ty = + fast_reject::simplify_type(self.tcx(), impl_ty, false); + + simplified_obligation_ty.is_some() + && simplified_impl_ty.is_some() + && simplified_obligation_ty != simplified_impl_ty + } + (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => { + // Lifetimes can never cause a rejection. + false + } + (GenericArgKind::Const(_), GenericArgKind::Const(_)) => { + // Conservatively ignore consts (i.e. assume they might + // unify later) until we have `fast_reject` support for + // them (if we'll ever need it, even). + false + } + _ => unreachable!(), + } }, ) } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 5a97a2af120d0..ff3493eb6de6d 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -563,30 +563,30 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { while !queue.is_empty() { let obligation = queue.remove(0); debug!("coerce_unsized resolve step: {:?}", obligation); - let trait_ref = match obligation.predicate { - ty::Predicate::Trait(ref tr, _) if traits.contains(&tr.def_id()) => { - if unsize_did == tr.def_id() { - let sty = &tr.skip_binder().input_types().nth(1).unwrap().kind; - if let ty::Tuple(..) = sty { + let trait_pred = match obligation.predicate { + ty::Predicate::Trait(trait_pred, _) if traits.contains(&trait_pred.def_id()) => { + if unsize_did == trait_pred.def_id() { + let unsize_ty = trait_pred.skip_binder().trait_ref.substs[1].expect_ty(); + if let ty::Tuple(..) = unsize_ty.kind { debug!("coerce_unsized: found unsized tuple coercion"); has_unsized_tuple_coercion = true; } } - *tr + trait_pred } _ => { coercion.obligations.push(obligation); continue; } }; - match selcx.select(&obligation.with(trait_ref)) { + match selcx.select(&obligation.with(trait_pred)) { // Uncertain or unimplemented. Ok(None) => { - if trait_ref.def_id() == unsize_did { - let trait_ref = self.resolve_vars_if_possible(&trait_ref); - let self_ty = trait_ref.skip_binder().self_ty(); - let unsize_ty = trait_ref.skip_binder().input_types().nth(1).unwrap(); - debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_ref); + if trait_pred.def_id() == unsize_did { + let trait_pred = self.resolve_vars_if_possible(&trait_pred); + let self_ty = trait_pred.skip_binder().self_ty(); + let unsize_ty = trait_pred.skip_binder().trait_ref.substs[1].expect_ty(); + debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred); match (&self_ty.kind, &unsize_ty.kind) { (ty::Infer(ty::TyVar(v)), ty::Dynamic(..)) if self.type_var_is_sized(*v) => diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f41114839020e..5c35dc5513266 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -84,15 +84,6 @@ impl, U> Clean> for Option { } } -impl Clean for ty::Binder -where - T: Clean, -{ - fn clean(&self, cx: &DocContext<'_>) -> U { - self.skip_binder().clean(cx) - } -} - impl Clean for CrateNum { fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate { let root = DefId { krate: *self, index: CRATE_DEF_INDEX }; @@ -305,59 +296,66 @@ impl Clean for hir::GenericBound<'_> { } } -impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec) { - fn clean(&self, cx: &DocContext<'_>) -> GenericBound { - let (trait_ref, ref bounds) = *self; +impl Clean for (ty::TraitRef<'_>, &[TypeBinding]) { + fn clean(&self, cx: &DocContext<'_>) -> Type { + let (trait_ref, bounds) = *self; inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait); let path = external_path( cx, cx.tcx.item_name(trait_ref.def_id), Some(trait_ref.def_id), true, - bounds.clone(), + bounds.to_vec(), trait_ref.substs, ); debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs); + ResolvedPath { path, param_names: None, did: trait_ref.def_id, is_generic: false } + } +} + +impl<'tcx> Clean for ty::TraitRef<'tcx> { + fn clean(&self, cx: &DocContext<'_>) -> GenericBound { + GenericBound::TraitBound( + PolyTrait { trait_: (*self, &[][..]).clean(cx), generic_params: vec![] }, + hir::TraitBoundModifier::None, + ) + } +} + +impl Clean for (ty::PolyTraitRef<'_>, &[TypeBinding]) { + fn clean(&self, cx: &DocContext<'_>) -> GenericBound { + let (poly_trait_ref, bounds) = *self; + let poly_trait_ref = poly_trait_ref.lift_to_tcx(cx.tcx).unwrap(); + // collect any late bound regions - let mut late_bounds = vec![]; - for ty_s in trait_ref.input_types().skip(1) { - if let ty::Tuple(ts) = ty_s.kind { - for &ty_s in ts { - if let ty::Ref(ref reg, _, _) = ty_s.expect_ty().kind { - if let &ty::RegionKind::ReLateBound(..) = *reg { - debug!(" hit an ReLateBound {:?}", reg); - if let Some(Lifetime(name)) = reg.clean(cx) { - late_bounds.push(GenericParamDef { - name, - kind: GenericParamDefKind::Lifetime, - }); - } - } - } - } - } - } + let late_bound_regions: Vec<_> = cx + .tcx + .collect_referenced_late_bound_regions(&poly_trait_ref) + .into_iter() + .filter_map(|br| match br { + ty::BrNamed(_, name) => Some(GenericParamDef { + name: name.to_string(), + kind: GenericParamDefKind::Lifetime, + }), + _ => None, + }) + .collect(); GenericBound::TraitBound( PolyTrait { - trait_: ResolvedPath { - path, - param_names: None, - did: trait_ref.def_id, - is_generic: false, - }, - generic_params: late_bounds, + trait_: (*poly_trait_ref.skip_binder(), bounds).clean(cx), + generic_params: late_bound_regions, }, hir::TraitBoundModifier::None, ) } } -impl<'tcx> Clean for ty::TraitRef<'tcx> { +impl<'tcx> Clean for ty::PolyTraitRef<'tcx> { fn clean(&self, cx: &DocContext<'_>) -> GenericBound { - (self, vec![]).clean(cx) + (*self, &[][..]).clean(cx) } } @@ -495,16 +493,17 @@ impl<'a> Clean> for ty::Predicate<'a> { } } -impl<'a> Clean for ty::TraitPredicate<'a> { +impl<'a> Clean for ty::PolyTraitPredicate<'a> { fn clean(&self, cx: &DocContext<'_>) -> WherePredicate { + let poly_trait_ref = self.map_bound(|pred| pred.trait_ref); WherePredicate::BoundPredicate { - ty: self.trait_ref.self_ty().clean(cx), - bounds: vec![self.trait_ref.clean(cx)], + ty: poly_trait_ref.self_ty().clean(cx), + bounds: vec![poly_trait_ref.clean(cx)], } } } -impl<'tcx> Clean for ty::SubtypePredicate<'tcx> { +impl<'tcx> Clean for ty::PolySubtypePredicate<'tcx> { fn clean(&self, _cx: &DocContext<'_>) -> WherePredicate { panic!( "subtype predicates are an internal rustc artifact \ @@ -514,10 +513,10 @@ impl<'tcx> Clean for ty::SubtypePredicate<'tcx> { } impl<'tcx> Clean> - for ty::OutlivesPredicate, ty::Region<'tcx>> + for ty::PolyOutlivesPredicate, ty::Region<'tcx>> { fn clean(&self, cx: &DocContext<'_>) -> Option { - let ty::OutlivesPredicate(ref a, ref b) = *self; + let ty::OutlivesPredicate(a, b) = self.skip_binder(); if let (ty::ReEmpty(_), ty::ReEmpty(_)) = (a, b) { return None; @@ -530,9 +529,9 @@ impl<'tcx> Clean> } } -impl<'tcx> Clean> for ty::OutlivesPredicate, ty::Region<'tcx>> { +impl<'tcx> Clean> for ty::PolyOutlivesPredicate, ty::Region<'tcx>> { fn clean(&self, cx: &DocContext<'_>) -> Option { - let ty::OutlivesPredicate(ref ty, ref lt) = *self; + let ty::OutlivesPredicate(ty, lt) = self.skip_binder(); if let ty::ReEmpty(_) = lt { return None; @@ -545,9 +544,10 @@ impl<'tcx> Clean> for ty::OutlivesPredicate, ty: } } -impl<'tcx> Clean for ty::ProjectionPredicate<'tcx> { +impl<'tcx> Clean for ty::PolyProjectionPredicate<'tcx> { fn clean(&self, cx: &DocContext<'_>) -> WherePredicate { - WherePredicate::EqPredicate { lhs: self.projection_ty.clean(cx), rhs: self.ty.clean(cx) } + let ty::ProjectionPredicate { projection_ty, ty } = *self.skip_binder(); + WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) } } } @@ -1674,7 +1674,7 @@ impl<'tcx> Clean for Ty<'tcx> { } } - let bounds = bounds + let bounds: Vec<_> = bounds .predicates .iter() .filter_map(|pred| { @@ -1703,7 +1703,7 @@ impl<'tcx> Clean for Ty<'tcx> { }) .collect(); - Some((trait_ref.skip_binder(), bounds).clean(cx)) + Some((trait_ref, &bounds[..]).clean(cx)) }) .collect::>(); bounds.extend(regions);