From 8696fa71b3ac0d8c468edc36502a304d38c7fd24 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 1 Aug 2023 00:52:16 +0000 Subject: [PATCH 1/3] Convert adt_sized_constraint to early-binder, use list --- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/adt.rs | 4 ++-- .../src/solve/assembly/structural_traits.rs | 2 +- .../rustc_trait_selection/src/traits/select/mod.rs | 2 +- compiler/rustc_ty_utils/src/ty.rs | 11 +++++++---- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 63df2830e0aa9..1189dcdfcbb3a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -706,7 +706,7 @@ rustc_queries! { separate_provide_extern } - query adt_sized_constraint(key: DefId) -> &'tcx [Ty<'tcx>] { + query adt_sized_constraint(key: DefId) -> ty::EarlyBinder<&'tcx ty::List>> { desc { |tcx| "computing `Sized` constraints for `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index e067d2a984fde..1bbbc0b8f7b60 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -572,8 +572,8 @@ impl<'tcx> AdtDef<'tcx> { /// /// Due to normalization being eager, this applies even if /// the associated type is behind a pointer (e.g., issue #31299). - pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]> { - ty::EarlyBinder::bind(tcx.adt_sized_constraint(self.did())) + pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx ty::List>> { + tcx.adt_sized_constraint(self.did()) } } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index a2db35e069eb7..72ba4f5913780 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -150,7 +150,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( ty::Adt(def, args) => { let sized_crit = def.sized_constraint(ecx.tcx()); - Ok(sized_crit.iter_instantiated_copied(ecx.tcx(), args).collect()) + Ok(sized_crit.iter_instantiated(ecx.tcx(), args).collect()) } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c29696bc817f7..6080a440de6b6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2099,7 +2099,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { Where( obligation .predicate - .rebind(sized_crit.iter_instantiated_copied(self.tcx(), args).collect()), + .rebind(sized_crit.iter_instantiated(self.tcx(), args).collect()), ) } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 791a1f4fa99a2..827df192e6611 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -42,7 +42,7 @@ fn sized_constraint_for_ty<'tcx>( let adt_tys = adt.sized_constraint(tcx); debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys); adt_tys - .iter_instantiated_copied(tcx, args) + .iter_instantiated(tcx, args) .flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty)) .collect() } @@ -92,10 +92,13 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness { /// - a tuple of type parameters or projections, if there are multiple /// such. /// - an Error, if a type is infinitely sized -fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] { +fn adt_sized_constraint<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, +) -> ty::EarlyBinder<&'tcx ty::List>> { if let Some(def_id) = def_id.as_local() { if matches!(tcx.representability(def_id), ty::Representability::Infinite) { - return tcx.mk_type_list(&[Ty::new_misc_error(tcx)]); + return ty::EarlyBinder::bind(tcx.mk_type_list(&[Ty::new_misc_error(tcx)])); } } let def = tcx.adt_def(def_id); @@ -107,7 +110,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] { debug!("adt_sized_constraint: {:?} => {:?}", def, result); - result + ty::EarlyBinder::bind(result) } /// See `ParamEnv` struct definition for details. From 44be25d8a2262a77ada651f0129b0ea6f8cb4755 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 1 Aug 2023 00:58:10 +0000 Subject: [PATCH 2/3] don't create a predicate for just a comparison --- compiler/rustc_ty_utils/src/ty.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 827df192e6611..08c405dfbcc8f 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -58,11 +58,17 @@ fn sized_constraint_for_ty<'tcx>( // we know that `T` is Sized and do not need to check // it on the impl. - let Some(sized_trait) = tcx.lang_items().sized_trait() else { return vec![ty] }; - let sized_predicate = - ty::TraitRef::new(tcx, sized_trait, [ty]).without_const().to_predicate(tcx); + let Some(sized_trait_def_id) = tcx.lang_items().sized_trait() else { return vec![ty] }; let predicates = tcx.predicates_of(adtdef.did()).predicates; - if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] } + if predicates.iter().any(|(p, _)| { + p.as_trait_clause().is_some_and(|trait_pred| { + trait_pred.def_id() == sized_trait_def_id && trait_pred.self_ty().skip_binder() == ty + }) + }) { + vec![] + } else { + vec![ty] + } } Placeholder(..) | Bound(..) | Infer(..) => { From ac6f2f0d2e6cb149f80903654cd603692bd06761 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 1 Aug 2023 00:59:59 +0000 Subject: [PATCH 3/3] Fix a comment --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 2 +- compiler/rustc_hir_typeck/src/closure.rs | 2 +- compiler/rustc_middle/src/ty/adt.rs | 12 ++---------- compiler/rustc_ty_utils/src/ty.rs | 3 ++- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 3235a9ceba1f0..bc109e7ad5170 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1462,7 +1462,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let traits: Vec<_> = self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident); - // Don't print `TyErr` to the user. + // Don't print `ty::Error` to the user. self.report_ambiguous_associated_type( span, &[qself_ty.to_string()], diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 0624a4baf79db..3e67afb1c3d9b 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -795,7 +795,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Converts the types that the user supplied, in case that doing /// so should yield an error, but returns back a signature where - /// all parameters are of type `TyErr`. + /// all parameters are of type `ty::Error`. fn error_sig_of_closure( &self, decl: &hir::FnDecl<'_>, diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 1bbbc0b8f7b60..6ba13a76563b3 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -562,16 +562,8 @@ impl<'tcx> AdtDef<'tcx> { tcx.adt_destructor(self.did()) } - /// Returns a list of types such that `Self: Sized` if and only - /// if that type is `Sized`, or `TyErr` if this type is recursive. - /// - /// Oddly enough, checking that the sized-constraint is `Sized` is - /// actually more expressive than checking all members: - /// the `Sized` trait is inductive, so an associated type that references - /// `Self` would prevent its containing ADT from being `Sized`. - /// - /// Due to normalization being eager, this applies even if - /// the associated type is behind a pointer (e.g., issue #31299). + /// Returns a list of types such that `Self: Sized` if and only if that + /// type is `Sized`, or `ty::Error` if this type has a recursive layout. pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx ty::List>> { tcx.adt_sized_constraint(self.did()) } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 08c405dfbcc8f..ba0258b63cb62 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -62,7 +62,8 @@ fn sized_constraint_for_ty<'tcx>( let predicates = tcx.predicates_of(adtdef.did()).predicates; if predicates.iter().any(|(p, _)| { p.as_trait_clause().is_some_and(|trait_pred| { - trait_pred.def_id() == sized_trait_def_id && trait_pred.self_ty().skip_binder() == ty + trait_pred.def_id() == sized_trait_def_id + && trait_pred.self_ty().skip_binder() == ty }) }) { vec![]