From a18571c7a1fe6e2f782305196a6aaf2047d75de2 Mon Sep 17 00:00:00 2001 From: jedel1043 Date: Mon, 19 Jul 2021 06:56:22 -0500 Subject: [PATCH] Skip implicit `Sized` bound for GATs' generics --- .../src/traits/project.rs | 3 +- .../src/traits/select/confirmation.rs | 15 ++++- .../src/traits/select/mod.rs | 8 ++- compiler/rustc_typeck/src/bounds.rs | 21 +++--- compiler/rustc_typeck/src/collect.rs | 65 ++++++++++++++++--- .../rustc_typeck/src/collect/item_bounds.rs | 8 +-- 6 files changed, 95 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index d1ab9fa025ed6..efdc4b89c2fae 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -327,8 +327,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { fn fold>(&mut self, value: T) -> T { let value = self.selcx.infcx().resolve_vars_if_possible(value); - debug!(?value); - + debug!(?value, "fold"); assert!( !value.has_escaping_bound_vars(), "Normalizing {:?} without wrapping in a `Binder`", diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index f8297ee3a0718..43f2ff6926916 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -130,8 +130,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); let trait_predicate = self.infcx.shallow_resolve(obligation.predicate); + debug!(?trait_predicate); + let placeholder_trait_predicate = self.infcx().replace_bound_vars_with_placeholders(trait_predicate); + debug!(?placeholder_trait_predicate); + let placeholder_self_ty = placeholder_trait_predicate.self_ty(); let (def_id, substs) = match *placeholder_self_ty.kind() { ty::Projection(proj) => (proj.item_def_id, proj.substs), @@ -140,9 +144,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs); + debug!("candidate predicate before poly trait = {:?}", candidate_predicate); + let candidate = candidate_predicate .to_opt_poly_trait_ref() .expect("projection candidate is not a trait predicate"); + debug!("candidate predicate after poly trait = {:?}", candidate_predicate); + let mut obligations = Vec::new(); let candidate = normalize_with_depth_to( self, @@ -162,7 +170,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { })?); if let ty::Projection(..) = placeholder_self_ty.kind() { - for predicate in tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates { + let predicates = tcx.predicates_of(def_id); + debug!(?predicates); + let instantiated_predicates = predicates.instantiate_own(tcx, substs); + debug!(?instantiated_predicates); + for predicate in instantiated_predicates.predicates { let normalized = normalize_with_depth_to( self, obligation.param_env, @@ -179,6 +191,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { )); } } + debug!(?obligations); Ok(obligations) }) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 564c63ef30cb6..53e1cae07052b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -868,7 +868,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { where I: Iterator>, { - cycle.all(|predicate| self.coinductive_predicate(predicate)) + cycle.all(|predicate| { + debug!(?predicate, "coinductive_match"); + self.coinductive_predicate(predicate) + }) } fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool { @@ -1572,8 +1575,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // NOTE: binder moved to (*) let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty()); + debug!(?self_ty, "sized_conditions"); - match self_ty.kind() { + match *self_ty.kind() { ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Uint(_) | ty::Int(_) diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_typeck/src/bounds.rs index 5d20064072263..ff62b86a43b7e 100644 --- a/compiler/rustc_typeck/src/bounds.rs +++ b/compiler/rustc_typeck/src/bounds.rs @@ -53,17 +53,22 @@ impl<'tcx> Bounds<'tcx> { &self, tcx: TyCtxt<'tcx>, param_ty: Ty<'tcx>, + skip_implicit_sized: bool, ) -> Vec<(ty::Predicate<'tcx>, Span)> { // If it could be sized, and is, add the `Sized` predicate. - let sized_predicate = self.implicitly_sized.and_then(|span| { - tcx.lang_items().sized_trait().map(|sized| { - let trait_ref = ty::Binder::dummy(ty::TraitRef { - def_id: sized, - substs: tcx.mk_substs_trait(param_ty, &[]), - }); - (trait_ref.without_const().to_predicate(tcx), span) + let sized_predicate = if skip_implicit_sized { + None + } else { + self.implicitly_sized.and_then(|span| { + tcx.lang_items().sized_trait().map(|sized| { + let trait_ref = ty::Binder::dummy(ty::TraitRef { + def_id: sized, + substs: tcx.mk_substs_trait(param_ty, &[]), + }); + (trait_ref.without_const().to_predicate(tcx), span) + }) }) - }); + }; sized_predicate .into_iter() diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 506ca98b96026..767f1df33907b 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1170,7 +1170,7 @@ fn super_predicates_that_define_assoc_type( ) }; - let superbounds1 = superbounds1.predicates(tcx, self_param_ty); + let superbounds1 = superbounds1.predicates(tcx, self_param_ty, false); // Convert any explicit superbounds in the where-clause, // e.g., `trait Foo where Self: Bar`. @@ -1978,6 +1978,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let node = tcx.hir().get(hir_id); + debug!("explicit_predicates_of: node = {:?}", node); let mut is_trait = None; let mut is_default_impl_trait = None; @@ -1991,10 +1992,22 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP // Preserving the order of insertion is important here so as not to break UI tests. let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default(); + let mut is_associated_type = false; + let ast_generics = match node { - Node::TraitItem(item) => &item.generics, + Node::TraitItem(item) => { + if matches!(item.kind, TraitItemKind::Type(..)) { + is_associated_type = true; + } + &item.generics + } - Node::ImplItem(item) => &item.generics, + Node::ImplItem(item) => { + if matches!(item.kind, ImplItemKind::TyAlias(..)) { + is_associated_type = true; + } + &item.generics + } Node::Item(item) => { match item.kind { @@ -2070,6 +2083,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP if let Some(_trait_ref) = is_trait { predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned()); } + debug!("explicit_predicates_of: super predicates = {:?}", predicates); // In default impls, we can assume that the self type implements // the trait. So in: @@ -2085,6 +2099,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP tcx.def_span(def_id), )); } + debug!("explicit_predicates_of: default impls = {:?}", predicates); // Collect the region predicates that were declared inline as // well. In the case of parameters declared on a fn or method, we @@ -2113,6 +2128,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } } + debug!("explicit_predicates_of: region predicates = {:?}", predicates); + // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). for param in ast_generics.params { @@ -2132,7 +2149,34 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP sized, param.span, ); - predicates.extend(bounds.predicates(tcx, param_ty)); + debug!("explicit_predicates_of: bounds = {:?}", bounds); + + // We need to skip from the predicate list the implicit Sized + // bound for the generic types inside a GAT in order to have recursion (#80626). + // For example, in: + // + // trait Allocator { + // type Allocated; + // } + // + // the GAT implicitly has the bound `Allocated: Sized`, but + // this bound generates a bound `T: Sized`, which we don't want + // because there are type constructors that can be sized without + // a `Sized` restriction on `T` (`Box`, `&T`, `*T`). + // However, we can't just remove the predicates with `Sized`, because + // if the user explicitly annotates `T` as `Sized` + // a trait implementation with `?Sized` could be unsound: + // + // impl Allocator for () { + // type Allocated = Box; + // } + // + // So we just skip the implicit `Sized` predicate on `predicates()` + predicates.extend(bounds.predicates( + tcx, + param_ty, + is_associated_type && bounds.implicitly_sized.is_some(), + )); } GenericParamKind::Const { .. } => { // Bounds on const parameters are currently not possible. @@ -2142,6 +2186,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } } + debug!("explicit_predicates_of: inline predicates = {:?}", predicates); + // Add in the bounds that appear in the where-clause. let where_clause = &ast_generics.where_clause; for predicate in where_clause.predicates { @@ -2194,7 +2240,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP &mut bounds, false, ); - predicates.extend(bounds.predicates(tcx, ty)); + predicates.extend(bounds.predicates(tcx, ty, false)); } &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { @@ -2208,7 +2254,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP ty, &mut bounds, ); - predicates.extend(bounds.predicates(tcx, ty)); + predicates.extend(bounds.predicates(tcx, ty, false)); } hir::GenericBound::Outlives(lifetime) => { @@ -2251,8 +2297,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } } + debug!("explicit_predicates_of: where predicates = {:?}", predicates); + if tcx.features().const_evaluatable_checked { predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local())); + debug!("explicit_predicates_of: const predicates = {:?}", predicates); } let mut predicates: Vec<_> = predicates.into_iter().collect(); @@ -2437,7 +2486,7 @@ fn predicates_from_bound<'tcx>( &mut bounds, false, ); - bounds.predicates(astconv.tcx(), param_ty) + bounds.predicates(astconv.tcx(), param_ty, false) } hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { let mut bounds = Bounds::default(); @@ -2449,7 +2498,7 @@ fn predicates_from_bound<'tcx>( param_ty, &mut bounds, ); - bounds.predicates(astconv.tcx(), param_ty) + bounds.predicates(astconv.tcx(), param_ty, false) } hir::GenericBound::Outlives(ref lifetime) => { let region = astconv.ast_region_to_region(lifetime, None); diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index a5b36445aae2e..38c93e8f6697f 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -45,9 +45,9 @@ fn associated_type_bounds<'tcx>( } }); - let all_bounds = tcx - .arena - .alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent)); + let all_bounds = tcx.arena.alloc_from_iter( + bounds.predicates(tcx, item_ty, false).into_iter().chain(bounds_from_parent), + ); debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds); all_bounds } @@ -73,7 +73,7 @@ fn opaque_type_bounds<'tcx>( SizedByDefault::Yes, span, ) - .predicates(tcx, item_ty); + .predicates(tcx, item_ty, false); debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds);