From 744417614a76c385123824fdcce19f75ddb1f165 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 29 Aug 2023 03:37:24 +0000 Subject: [PATCH 1/8] Allow bounds on non-lifetime binders --- compiler/rustc_ast_passes/src/feature_gate.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 34532967d9e24..7c1206632b625 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -170,10 +170,12 @@ impl<'a> PostExpansionVisitor<'a> { ) .emit(); } - for param in params { - if !param.bounds.is_empty() { - let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); - self.sess.emit_err(errors::ForbiddenLifetimeBound { spans }); + if !self.features.non_lifetime_binders { + for param in params { + if !param.bounds.is_empty() { + let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); + self.sess.emit_err(errors::ForbiddenLifetimeBound { spans }); + } } } } From 4f878fed25dd772914175c4e47d9a5203590f28b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 29 Aug 2023 18:00:27 +0000 Subject: [PATCH 2/8] More non-lifetime binder stuff --- compiler/rustc_ast_lowering/src/item.rs | 15 ++ compiler/rustc_hir/src/hir.rs | 4 +- compiler/rustc_hir/src/intravisit.rs | 2 + .../rustc_hir_analysis/src/astconv/bounds.rs | 139 +++++++++++++++++- .../rustc_hir_analysis/src/astconv/mod.rs | 4 + .../src/astconv/object_safety.rs | 2 + compiler/rustc_hir_analysis/src/bounds.rs | 5 +- .../src/collect/predicates_of.rs | 102 +------------ .../src/collect/resolve_bound_vars.rs | 2 + compiler/rustc_hir_analysis/src/lib.rs | 2 + 10 files changed, 178 insertions(+), 99 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 3c165f87dbf3d..b0948729840bb 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1600,6 +1600,7 @@ impl<'hir> LoweringContext<'_, 'hir> { bounds, span, bound_generic_params: &[], + binder_predicates: &[], origin, })) } @@ -1628,6 +1629,20 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: self.next_id(), bound_generic_params: self .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder), + binder_predicates: self.arena.alloc_from_iter( + bound_generic_params.iter().filter_map(|param| { + self.lower_generic_bound_predicate( + param.ident, + param.id, + ¶m.kind, + ¶m.bounds, + param.colon_span, + *span, + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + PredicateOrigin::GenericParam, + ) + }), + ), bounded_ty: self .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), bounds: self.lower_param_bounds( diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 63711f5804d68..5911e3fee238b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -779,9 +779,11 @@ pub struct WhereBoundPredicate<'hir> { pub origin: PredicateOrigin, /// Any generics from a `for` binding. pub bound_generic_params: &'hir [GenericParam<'hir>], + /// Predicates on the `for` binder itself, such as `for ...` + pub binder_predicates: &'hir [WherePredicate<'hir>], /// The type being bounded. pub bounded_ty: &'hir Ty<'hir>, - /// Trait and lifetime bounds (e.g., `Clone + Send + 'static`). + /// Trait and lifetime bounds for `bounded_ty` (e.g., `Clone + Send + 'static`). pub bounds: GenericBounds<'hir>, } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 8a67285598998..0e86f19f8c106 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -904,11 +904,13 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( bound_generic_params, origin: _, span: _, + binder_predicates, }) => { visitor.visit_id(hir_id); visitor.visit_ty(bounded_ty); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_generic_param, bound_generic_params); + walk_list!(visitor, visit_where_predicate, binder_predicates); } WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 711da6db5accb..9aa421573d836 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -1,10 +1,10 @@ -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_lint_defs::Applicability; -use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self as ty, ToPredicate, Ty, TypeVisitableExt}; use rustc_span::symbol::Ident; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; @@ -16,6 +16,132 @@ use crate::bounds::Bounds; use crate::errors; impl<'tcx> dyn AstConv<'tcx> + '_ { + pub(crate) fn lower_where_predicates( + &self, + params: &'tcx [hir::GenericParam<'tcx>], + hir_predicates: &'tcx [hir::WherePredicate<'tcx>], + predicates: &mut FxIndexSet<(ty::Clause<'tcx>, Span)>, + ) { + // Collect the predicates that were written inline by the user on each + // type parameter (e.g., ``). Also add `ConstArgHasType` predicates + // for each const parameter. + for param in params { + match param.kind { + hir::GenericParamKind::Lifetime { .. } => (), + hir::GenericParamKind::Type { .. } => { + let param_ty = + ty::fold::shift_vars(self.tcx(), self.hir_id_to_bound_ty(param.hir_id), 1); + let mut bounds = Bounds::default(); + // Params are implicitly sized unless a `?Sized` bound is found + self.add_implicitly_sized( + &mut bounds, + param_ty, + &[], + Some((param.def_id, hir_predicates)), + param.span, + ); + trace!(?bounds); + predicates.extend(bounds.clauses()); + trace!(?predicates); + } + hir::GenericParamKind::Const { .. } => { + let ct_ty = self + .tcx() + .type_of(param.def_id.to_def_id()) + .no_bound_vars() + .expect("const parameters cannot be generic"); + let ct = ty::fold::shift_vars( + self.tcx(), + self.hir_id_to_bound_const(param.hir_id, ct_ty), + 1, + ); + predicates.insert(( + ty::Binder::bind_with_vars( + ty::ClauseKind::ConstArgHasType(ct, ct_ty), + ty::List::empty(), + ) + .to_predicate(self.tcx()), + param.span, + )); + } + } + } + + // Add in the bounds that appear in the where-clause. + for predicate in hir_predicates { + match predicate { + hir::WherePredicate::BoundPredicate(bound_pred) => { + let ty = self.ast_ty_to_ty(bound_pred.bounded_ty); + let bound_vars = self.tcx().late_bound_vars(bound_pred.hir_id); + + let mut binder_predicates = FxIndexSet::default(); + self.lower_where_predicates( + bound_pred.bound_generic_params, + bound_pred.binder_predicates, + &mut binder_predicates, + ); + let binder_predicates = self.tcx().mk_clauses_from_iter( + binder_predicates.into_iter().map(|(clause, _)| clause), + ); + if !binder_predicates.is_empty() { + println!("binder_predicates = {binder_predicates:#?}"); + } + + // Keep the type around in a dummy predicate, in case of no bounds. + // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` + // is still checked for WF. + if bound_pred.bounds.is_empty() { + if let ty::Param(_) = ty.kind() { + // This is a `where T:`, which can be in the HIR from the + // transformation that moves `?Sized` to `T`'s declaration. + // We can skip the predicate because type parameters are + // trivially WF, but also we *should*, to avoid exposing + // users who never wrote `where Type:,` themselves, to + // compiler/tooling bugs from not handling WF predicates. + } else { + let span = bound_pred.bounded_ty.span; + let predicate = ty::Binder::bind_with_vars( + ty::ClauseKind::WellFormed(ty.into()), + bound_vars, + ); + predicates.insert((predicate.to_predicate(self.tcx()), span)); + } + } + + let mut bounds = Bounds::default(); + self.add_bounds( + ty, + bound_pred.bounds.iter(), + &mut bounds, + bound_vars, + binder_predicates, + OnlySelfBounds(false), + ); + predicates.extend(bounds.clauses()); + } + + hir::WherePredicate::RegionPredicate(region_pred) => { + let r1 = self.ast_region_to_region(®ion_pred.lifetime, None); + predicates.extend(region_pred.bounds.iter().map(|bound| { + let (r2, span) = match bound { + hir::GenericBound::Outlives(lt) => { + (self.ast_region_to_region(lt, None), lt.ident.span) + } + _ => bug!(), + }; + let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)) + .to_predicate(self.tcx()); + (pred, span) + })) + } + + hir::WherePredicate::EqPredicate(..) => { + // FIXME(#20041) + } + } + } + } + /// Sets `implicitly_sized` to true on `Bounds` if necessary pub(crate) fn add_implicitly_sized( &self, @@ -102,6 +228,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { ast_bounds: I, bounds: &mut Bounds<'tcx>, bound_vars: &'tcx ty::List, + binder_predicates: &'tcx ty::List>, only_self_bounds: OnlySelfBounds, ) { for ast_bound in ast_bounds { @@ -119,6 +246,10 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { } hir::TraitBoundModifier::Maybe => continue, }; + + // TODO: Add in the binder preds from the poly trait ref. + let binder_predicates = binder_predicates; + let _ = self.instantiate_poly_trait_ref( &poly_trait_ref.trait_ref, poly_trait_ref.span, @@ -127,6 +258,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { param_ty, bounds, false, + binder_predicates, only_self_bounds, ); } @@ -208,6 +340,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { }), &mut bounds, ty::List::empty(), + ty::List::empty(), only_self_bounds, ); debug!(?bounds); @@ -577,6 +710,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { ast_bounds.iter(), bounds, projection_ty.bound_vars(), + // TODO: This is wrong, should take preds from binder + ty::List::empty(), only_self_bounds, ); } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 2fcb45ef8aa12..abedd92d09129 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -687,6 +687,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args: &GenericArgs<'_>, infer_args: bool, self_ty: Ty<'tcx>, + _binder_predicates: &'tcx ty::List>, only_self_bounds: OnlySelfBounds, ) -> GenericArgCountResult { let (generic_args, arg_count) = self.create_args_for_ast_path( @@ -774,6 +775,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, speculative: bool, + binder_predicates: &'tcx ty::List>, only_self_bounds: OnlySelfBounds, ) -> GenericArgCountResult { let hir_id = trait_ref.hir_ref_id; @@ -801,6 +803,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args, infer_args, self_ty, + binder_predicates, only_self_bounds, ) } @@ -837,6 +840,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args, infer_args, self_ty, + ty::List::empty(), only_self_bounds, ); } diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 30c2ab8f5458c..3d8cc1cbaa15b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -46,6 +46,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { dummy_self, &mut bounds, false, + // TODO: dyn traits should have no binder preds + ty::List::empty(), // FIXME: This should be `true`, but we don't really handle // associated type bounds or type aliases in objects in a way // that makes this meaningful, I think. diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index b6688e0ce29e0..628ec5ee8c6be 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -98,7 +98,10 @@ impl<'tcx> Bounds<'tcx> { let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span)); let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]); // Preferable to put this obligation first, since we report better errors for sized ambiguity. - self.clauses.insert(0, (trait_ref.to_predicate(tcx), span)); + self.clauses.insert( + 0, + (ty::Binder::bind_with_vars(trait_ref, ty::List::empty()).to_predicate(tcx), span), + ); } pub fn clauses(&self) -> impl Iterator, Span)> + '_ { diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 104da581e019d..e0a05b440e98d 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -214,101 +214,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen predicates.insert((trait_ref.to_predicate(tcx), tcx.def_span(def_id))); } - // Collect the predicates that were written inline by the user on each - // type parameter (e.g., ``). Also add `ConstArgHasType` predicates - // for each const parameter. - for param in ast_generics.params { - match param.kind { - // We already dealt with early bound lifetimes above. - GenericParamKind::Lifetime { .. } => (), - GenericParamKind::Type { .. } => { - let param_ty = icx.astconv().hir_id_to_bound_ty(param.hir_id); - let mut bounds = Bounds::default(); - // Params are implicitly sized unless a `?Sized` bound is found - icx.astconv().add_implicitly_sized( - &mut bounds, - param_ty, - &[], - Some((param.def_id, ast_generics.predicates)), - param.span, - ); - trace!(?bounds); - predicates.extend(bounds.clauses()); - trace!(?predicates); - } - hir::GenericParamKind::Const { .. } => { - let ct_ty = tcx - .type_of(param.def_id.to_def_id()) - .no_bound_vars() - .expect("const parameters cannot be generic"); - let ct = icx.astconv().hir_id_to_bound_const(param.hir_id, ct_ty); - predicates.insert(( - ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx), - param.span, - )); - } - } - } - - trace!(?predicates); - // Add in the bounds that appear in the where-clause. - for predicate in ast_generics.predicates { - match predicate { - hir::WherePredicate::BoundPredicate(bound_pred) => { - let ty = icx.to_ty(bound_pred.bounded_ty); - let bound_vars = tcx.late_bound_vars(bound_pred.hir_id); - // Keep the type around in a dummy predicate, in case of no bounds. - // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` - // is still checked for WF. - if bound_pred.bounds.is_empty() { - if let ty::Param(_) = ty.kind() { - // This is a `where T:`, which can be in the HIR from the - // transformation that moves `?Sized` to `T`'s declaration. - // We can skip the predicate because type parameters are - // trivially WF, but also we *should*, to avoid exposing - // users who never wrote `where Type:,` themselves, to - // compiler/tooling bugs from not handling WF predicates. - } else { - let span = bound_pred.bounded_ty.span; - let predicate = ty::Binder::bind_with_vars( - ty::ClauseKind::WellFormed(ty.into()), - bound_vars, - ); - predicates.insert((predicate.to_predicate(tcx), span)); - } - } - - let mut bounds = Bounds::default(); - icx.astconv().add_bounds( - ty, - bound_pred.bounds.iter(), - &mut bounds, - bound_vars, - OnlySelfBounds(false), - ); - predicates.extend(bounds.clauses()); - } - - hir::WherePredicate::RegionPredicate(region_pred) => { - let r1 = icx.astconv().ast_region_to_region(®ion_pred.lifetime, None); - predicates.extend(region_pred.bounds.iter().map(|bound| { - let (r2, span) = match bound { - hir::GenericBound::Outlives(lt) => { - (icx.astconv().ast_region_to_region(lt, None), lt.ident.span) - } - _ => bug!(), - }; - let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)) - .to_predicate(tcx); - (pred, span) - })) - } - - hir::WherePredicate::EqPredicate(..) => { - // FIXME(#20041) - } - } - } + icx.astconv().lower_where_predicates( + &ast_generics.params, + &ast_generics.predicates, + &mut predicates, + ); if tcx.features().generic_const_exprs { predicates.extend(const_evaluatable_predicates_of(tcx, def_id)); @@ -823,6 +733,8 @@ impl<'tcx> ItemCtxt<'tcx> { }), &mut bounds, bound_vars, + // TODO: convert `where_bound_predicate` above accordingly + ty::List::empty(), only_self_bounds, ); } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index ebb9e6f42d987..bb1e2145b8b90 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -868,6 +868,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { bounds, bound_generic_params, origin, + binder_predicates, .. }) => { let (bound_vars, binders): (FxIndexMap, Vec<_>) = @@ -896,6 +897,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { walk_list!(this, visit_generic_param, bound_generic_params); this.visit_ty(&bounded_ty); walk_list!(this, visit_param_bound, bounds); + walk_list!(this, visit_where_predicate, binder_predicates); }) } &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index f27ce7fa0e016..b643dc6eeaba6 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -265,6 +265,8 @@ pub fn hir_trait_to_predicates<'tcx>( self_ty, &mut bounds, true, + // TODO: This is probably wrong! + ty::List::empty(), OnlySelfBounds(false), ); From b92c98e923dc5551b4cfb1d69a9a34863ed67121 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 29 Aug 2023 18:18:01 +0000 Subject: [PATCH 3/8] Binders have predicates now --- .../rustc_hir_analysis/src/astconv/mod.rs | 5 +- .../src/infer/higher_ranked/mod.rs | 2 + compiler/rustc_infer/src/infer/mod.rs | 2 + .../rustc_infer/src/infer/nll_relate/mod.rs | 4 + compiler/rustc_middle/src/ty/mod.rs | 116 ++++++++++++++++-- compiler/rustc_middle/src/ty/sty.rs | 61 ++++++--- 6 files changed, 160 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index abedd92d09129..bb974c02c776f 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -687,7 +687,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args: &GenericArgs<'_>, infer_args: bool, self_ty: Ty<'tcx>, - _binder_predicates: &'tcx ty::List>, + binder_predicates: &'tcx ty::List>, only_self_bounds: OnlySelfBounds, ) -> GenericArgCountResult { let (generic_args, arg_count) = self.create_args_for_ast_path( @@ -707,9 +707,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let assoc_bindings = self.create_assoc_bindings_for_generic_args(args); - let poly_trait_ref = ty::Binder::bind_with_vars( + let poly_trait_ref = ty::Binder::bind_with_vars_and_predicates( ty::TraitRef::new(tcx, trait_def_id, generic_args), bound_vars, + binder_predicates, ); debug!(?poly_trait_ref, ?assoc_bindings); diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index 510b1797d3c9b..e0c87c675ce94 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -74,6 +74,8 @@ impl<'tcx> InferCtxt<'tcx> { where T: TypeFoldable> + Copy, { + assert_eq!(binder.skip_binder_predicates(), ty::List::empty()); + if let Some(inner) = binder.no_bound_vars() { return inner; } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 4ee897ffe9843..eb89292a8bd4d 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1468,6 +1468,8 @@ impl<'tcx> InferCtxt<'tcx> { where T: TypeFoldable> + Copy, { + assert_eq!(value.skip_binder_predicates(), ty::List::empty()); + if let Some(inner) = value.no_bound_vars() { return inner; } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index c80491643913c..d880e6bf991b0 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -263,6 +263,8 @@ where where T: ty::TypeFoldable> + Copy, { + assert_eq!(binder.skip_binder_predicates(), ty::List::empty()); + if let Some(inner) = binder.no_bound_vars() { return inner; } @@ -311,6 +313,8 @@ where where T: ty::TypeFoldable> + Copy, { + assert_eq!(binder.skip_binder_predicates(), ty::List::empty()); + if let Some(inner) = binder.no_bound_vars() { return inner; } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index cc0db39ac5719..603863415cb4a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -97,7 +97,7 @@ pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::BoundRegionKind::*; pub use self::sty::{ AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, - BoundVariableKind, CanonicalPolyFnSig, ClauseKind, ClosureArgs, ClosureArgsParts, ConstKind, + BoundVariableKind, CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, ConstKind, ConstVid, CoroutineArgs, CoroutineArgsParts, EarlyBoundRegion, EffectVid, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection, @@ -244,8 +244,8 @@ pub enum ImplSubject<'tcx> { Inherent(Ty<'tcx>), } -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] +#[derive(HashStable, TypeFoldable, TypeVisitable, TyEncodable, TyDecodable)] pub enum ImplPolarity { /// `impl Trait for Type` Positive, @@ -573,7 +573,7 @@ impl rustc_errors::IntoDiagnosticArg for Clause<'_> { /// A subset of predicates which can be assumed by the trait solver. They show up in /// an item's where clauses, hence the name `Clause`, and may either be user-written /// (such as traits) or may be inserted during lowering. -#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] #[rustc_pass_by_value] pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo>>>); @@ -626,6 +626,98 @@ impl<'tcx> Clause<'tcx> { } } +#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)] +/// A clause is something that can appear in where bounds or be inferred +/// by implied bounds. +pub enum ClauseKind<'tcx> { + /// Corresponds to `where Foo: Bar`. `Foo` here would be + /// the `Self` type of the trait reference and `A`, `B`, and `C` + /// would be the type parameters. + Trait(TraitPredicate<'tcx>), + + /// `where 'a: 'b` + RegionOutlives(RegionOutlivesPredicate<'tcx>), + + /// `where T: 'a` + TypeOutlives(TypeOutlivesPredicate<'tcx>), + + /// `where ::Name == X`, approximately. + /// See the `ProjectionPredicate` struct for details. + Projection(ProjectionPredicate<'tcx>), + + /// Ensures that a const generic argument to a parameter `const N: u8` + /// is of type `u8`. + ConstArgHasType(Const<'tcx>, Ty<'tcx>), + + /// No syntax: `T` well-formed. + WellFormed(GenericArg<'tcx>), + + /// Constant initializer must evaluate successfully. + ConstEvaluatable(ty::Const<'tcx>), +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)] +pub enum PredicateKind<'tcx> { + /// Prove a clause + Clause(ClauseKind<'tcx>), + + /// Trait must be object-safe. + ObjectSafe(DefId), + + /// No direct syntax. May be thought of as `where T: FnFoo<...>` + /// for some generic args `...` and `T` being a closure type. + /// Satisfied (or refuted) once we know the closure's kind. + ClosureKind(DefId, GenericArgsRef<'tcx>, ClosureKind), + + /// `T1 <: T2` + /// + /// This obligation is created most often when we have two + /// unresolved type variables and hence don't have enough + /// information to process the subtyping obligation yet. + Subtype(SubtypePredicate<'tcx>), + + /// `T1` coerced to `T2` + /// + /// Like a subtyping obligation, this is created most often + /// when we have two unresolved type variables and hence + /// don't have enough information to process the coercion + /// obligation yet. At the moment, we actually process coercions + /// very much like subtyping and don't handle the full coercion + /// logic. + Coerce(CoercePredicate<'tcx>), + + /// Constants must be equal. The first component is the const that is expected. + ConstEquate(Const<'tcx>, Const<'tcx>), + + /// A marker predicate that is always ambiguous. + /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous. + Ambiguous, + + /// Separate from `ClauseKind::Projection` which is used for normalization in new solver. + /// This predicate requires two terms to be equal to eachother. + /// + /// Only used for new solver + AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection), +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(HashStable, Debug, TyEncodable, TyDecodable)] +pub enum AliasRelationDirection { + Equate, + Subtype, +} + +impl std::fmt::Display for AliasRelationDirection { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AliasRelationDirection::Equate => write!(f, "=="), + AliasRelationDirection::Subtype => write!(f, "<:"), + } + } +} + /// The crate outlives map is computed during typeck and contains the /// outlives of every item in the local crate. You should not use it /// directly, because to do so will make your pass dependent on the @@ -746,8 +838,8 @@ impl<'tcx> Clause<'tcx> { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)] pub struct TraitPredicate<'tcx> { pub trait_ref: TraitRef<'tcx>, @@ -805,8 +897,8 @@ pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicat /// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates /// whether the `a` type is the type that we should label as "expected" when /// presenting user diagnostics. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)] pub struct SubtypePredicate<'tcx> { pub a_is_expected: bool, pub a: Ty<'tcx>, @@ -815,8 +907,8 @@ pub struct SubtypePredicate<'tcx> { pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; /// Encodes that we have to coerce *from* the `a` type to the `b` type. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)] pub struct CoercePredicate<'tcx> { pub a: Ty<'tcx>, pub b: Ty<'tcx>, @@ -1021,8 +1113,8 @@ impl From for TermVid { /// equality between arbitrary types. Processing an instance of /// Form #2 eventually yields one of these `ProjectionPredicate` /// instances to normalize the LHS. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)] pub struct ProjectionPredicate<'tcx> { pub projection_ty: AliasTy<'tcx>, pub term: Term<'tcx>, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 44592b10d5574..61cf534095af9 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1003,6 +1003,7 @@ impl BoundVariableKind { pub struct Binder<'tcx, T> { value: T, bound_vars: &'tcx List, + bound_predicates: &'tcx List>, } impl<'tcx, T> Binder<'tcx, T> @@ -1019,7 +1020,7 @@ where !value.has_escaping_bound_vars(), "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder." ); - Binder { value, bound_vars: ty::List::empty() } + Binder { value, bound_vars: ty::List::empty(), bound_predicates: ty::List::empty() } } pub fn bind_with_vars(value: T, bound_vars: &'tcx List) -> Binder<'tcx, T> { @@ -1027,11 +1028,28 @@ where let mut validator = ValidateBoundVars::new(bound_vars); value.visit_with(&mut validator); } - Binder { value, bound_vars } + Binder { value, bound_vars, bound_predicates: ty::List::empty() } + } + + pub fn bind_with_vars_and_predicates( + value: T, + bound_vars: &'tcx List, + bound_predicates: &'tcx List>, + ) -> Binder<'tcx, T> { + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(bound_vars); + value.visit_with(&mut validator); + bound_predicates.visit_with(&mut validator); + } + Binder { value, bound_vars, bound_predicates } } } impl<'tcx, T> Binder<'tcx, T> { + pub fn skip_binder_predicates(self) -> &'tcx List> { + self.bound_predicates + } + /// Skips the binder and returns the "bound" value. This is a /// risky thing to do because it's easy to get confused about /// De Bruijn indices and the like. It is usually better to @@ -1057,14 +1075,22 @@ impl<'tcx, T> Binder<'tcx, T> { } pub fn as_ref(&self) -> Binder<'tcx, &T> { - Binder { value: &self.value, bound_vars: self.bound_vars } + Binder { + value: &self.value, + bound_vars: self.bound_vars, + bound_predicates: self.bound_predicates, + } } pub fn as_deref(&self) -> Binder<'tcx, &T::Target> where T: Deref, { - Binder { value: &self.value, bound_vars: self.bound_vars } + Binder { + value: &self.value, + bound_vars: self.bound_vars, + bound_predicates: self.bound_predicates, + } } pub fn map_bound_ref_unchecked(&self, f: F) -> Binder<'tcx, U> @@ -1072,7 +1098,7 @@ impl<'tcx, T> Binder<'tcx, T> { F: FnOnce(&T) -> U, { let value = f(&self.value); - Binder { value, bound_vars: self.bound_vars } + Binder { value, bound_vars: self.bound_vars, bound_predicates: self.bound_predicates } } pub fn map_bound_ref>>(&self, f: F) -> Binder<'tcx, U> @@ -1086,13 +1112,13 @@ impl<'tcx, T> Binder<'tcx, T> { where F: FnOnce(T) -> U, { - let Binder { value, bound_vars } = self; + let Binder { value, bound_vars, bound_predicates } = self; let value = f(value); if cfg!(debug_assertions) { let mut validator = ValidateBoundVars::new(bound_vars); value.visit_with(&mut validator); } - Binder { value, bound_vars } + Binder { value, bound_vars, bound_predicates } } pub fn try_map_bound>, E>( @@ -1102,13 +1128,13 @@ impl<'tcx, T> Binder<'tcx, T> { where F: FnOnce(T) -> Result, { - let Binder { value, bound_vars } = self; + let Binder { value, bound_vars, bound_predicates } = self; let value = f(value)?; if cfg!(debug_assertions) { let mut validator = ValidateBoundVars::new(bound_vars); value.visit_with(&mut validator); } - Ok(Binder { value, bound_vars }) + Ok(Binder { value, bound_vars, bound_predicates }) } /// Wraps a `value` in a binder, using the same bound variables as the @@ -1124,7 +1150,7 @@ impl<'tcx, T> Binder<'tcx, T> { where U: TypeVisitable>, { - Binder::bind_with_vars(value, self.bound_vars) + Binder::bind_with_vars_and_predicates(value, self.bound_vars, self.bound_predicates) } /// Unwraps and returns the value within, but only if it contains @@ -1154,23 +1180,26 @@ impl<'tcx, T> Binder<'tcx, T> { where F: FnOnce(T) -> (U, V), { - let Binder { value, bound_vars } = self; + let Binder { value, bound_vars, bound_predicates } = self; let (u, v) = f(value); - (Binder { value: u, bound_vars }, Binder { value: v, bound_vars }) + ( + Binder { value: u, bound_vars, bound_predicates }, + Binder { value: v, bound_vars, bound_predicates }, + ) } } impl<'tcx, T> Binder<'tcx, Option> { pub fn transpose(self) -> Option> { - let Binder { value, bound_vars } = self; - value.map(|value| Binder { value, bound_vars }) + let Binder { value, bound_vars, bound_predicates } = self; + value.map(|value| Binder { value, bound_vars, bound_predicates }) } } impl<'tcx, T: IntoIterator> Binder<'tcx, T> { pub fn iter(self) -> impl Iterator> { - let Binder { value, bound_vars } = self; - value.into_iter().map(|value| Binder { value, bound_vars }) + let Binder { value, bound_vars, bound_predicates } = self; + value.into_iter().map(|value| Binder { value, bound_vars, bound_predicates }) } } From 18a9b8785123afc7fa944357a8b40671271a79e0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 29 Aug 2023 19:31:08 +0000 Subject: [PATCH 4/8] Handle binder predicates in new trait solver --- .../rustc_hir_analysis/src/astconv/bounds.rs | 6 +- .../src/infer/higher_ranked/mod.rs | 49 ++++++++++++++ compiler/rustc_infer/src/infer/mod.rs | 65 +++++++++++++++++++ compiler/rustc_middle/src/ty/fold.rs | 9 +++ compiler/rustc_middle/src/ty/mod.rs | 11 ++++ compiler/rustc_middle/src/ty/sty.rs | 2 +- .../src/solve/eval_ctxt/mod.rs | 31 ++++++++- .../src/solve/project_goals/mod.rs | 6 +- .../src/solve/trait_goals.rs | 5 +- 9 files changed, 172 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 9aa421573d836..b99fbbc120c73 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -83,9 +83,6 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let binder_predicates = self.tcx().mk_clauses_from_iter( binder_predicates.into_iter().map(|(clause, _)| clause), ); - if !binder_predicates.is_empty() { - println!("binder_predicates = {binder_predicates:#?}"); - } // Keep the type around in a dummy predicate, in case of no bounds. // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` @@ -710,8 +707,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { ast_bounds.iter(), bounds, projection_ty.bound_vars(), - // TODO: This is wrong, should take preds from binder - ty::List::empty(), + projection_ty.skip_binder_predicates(), only_self_bounds, ); } diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index e0c87c675ce94..7c693b67cda51 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -108,6 +108,55 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx.replace_bound_vars_uncached(binder, delegate) } + /// Replaces all bound variables (lifetimes, types, and constants) bound by + /// `binder` with placeholder variables in a new universe. This means that the + /// new placeholders can only be named by inference variables created after + /// this method has been called. + /// + /// This is the first step of checking subtyping when higher-ranked things are involved. + /// For more details visit the relevant sections of the [rustc dev guide]. + /// + /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html + #[instrument(level = "debug", skip(self), ret)] + pub fn instantiate_binder_and_assumptions_with_placeholders( + &self, + binder: ty::Binder<'tcx, T>, + ) -> (T, &'tcx ty::List>) + where + T: TypeFoldable> + Copy, + { + if let Some(inner) = binder.no_bound_vars() { + return (inner, ty::List::empty()); + } + + let next_universe = self.create_next_universe(); + + let delegate = FnMutDelegate { + regions: &mut |br: ty::BoundRegion| { + ty::Region::new_placeholder( + self.tcx, + ty::PlaceholderRegion { universe: next_universe, bound: br }, + ) + }, + types: &mut |bound_ty: ty::BoundTy| { + Ty::new_placeholder( + self.tcx, + ty::PlaceholderType { universe: next_universe, bound: bound_ty }, + ) + }, + consts: &mut |bound_var: ty::BoundVar, ty| { + ty::Const::new_placeholder( + self.tcx, + ty::PlaceholderConst { universe: next_universe, bound: bound_var }, + ty, + ) + }, + }; + + debug!(?next_universe); + self.tcx.replace_bound_vars_and_predicates_uncached(binder, delegate) + } + /// See [RegionConstraintCollector::leak_check][1]. We only check placeholder /// leaking into `outer_universe`, i.e. placeholders which cannot be named by that /// universe. diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index eb89292a8bd4d..b903dd00ce1f6 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1526,6 +1526,71 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx.replace_bound_vars_uncached(value, delegate) } + pub fn instantiate_binder_and_predicates_with_fresh_vars( + &self, + span: Span, + lbrct: LateBoundRegionConversionTime, + value: ty::Binder<'tcx, T>, + ) -> (T, &'tcx ty::List>) + where + T: TypeFoldable> + Copy, + { + if let Some(inner) = value.no_bound_vars() { + return (inner, ty::List::empty()); + } + + struct ToFreshVars<'a, 'tcx> { + infcx: &'a InferCtxt<'tcx>, + span: Span, + lbrct: LateBoundRegionConversionTime, + map: FxHashMap>, + } + + impl<'tcx> BoundVarReplacerDelegate<'tcx> for ToFreshVars<'_, 'tcx> { + fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> { + self.map + .entry(br.var) + .or_insert_with(|| { + self.infcx + .next_region_var(LateBoundRegion(self.span, br.kind, self.lbrct)) + .into() + }) + .expect_region() + } + fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { + self.map + .entry(bt.var) + .or_insert_with(|| { + self.infcx + .next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span: self.span, + }) + .into() + }) + .expect_ty() + } + fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> { + self.map + .entry(bv) + .or_insert_with(|| { + self.infcx + .next_const_var( + ty, + ConstVariableOrigin { + kind: ConstVariableOriginKind::MiscVariable, + span: self.span, + }, + ) + .into() + }) + .expect_const() + } + } + let delegate = ToFreshVars { infcx: self, span, lbrct, map: Default::default() }; + self.tcx.replace_bound_vars_and_predicates_uncached(value, delegate) + } + /// See the [`region_constraints::RegionConstraintCollector::verify_generic_bound`] method. pub fn verify_generic_bound( &self, diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 00529a1e066cc..900360ca7dc21 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -317,6 +317,15 @@ impl<'tcx> TyCtxt<'tcx> { self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate) } + pub fn replace_bound_vars_and_predicates_uncached>>( + self, + value: Binder<'tcx, T>, + delegate: impl BoundVarReplacerDelegate<'tcx>, + ) -> (T, &'tcx ty::List>) { + let preds = value.skip_binder_predicates(); + self.replace_escaping_bound_vars_uncached((value.skip_binder(), preds), delegate) + } + /// Replaces any late-bound regions bound in `value` with /// free variants attached to `all_outlive_scope`. pub fn liberate_late_bound_regions( diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 603863415cb4a..ed1348ce324dc 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1724,6 +1724,17 @@ impl<'tcx> ParamEnv<'tcx> { ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal }) } } + pub fn augment( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + more_caller_bounds: &'tcx List>, + ) -> Self { + ty::ParamEnv::new( + tcx.mk_clauses_from_iter(param_env.caller_bounds().iter().chain(more_caller_bounds)), + param_env.reveal(), + ) + } + pub fn with_user_facing(mut self) -> Self { self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() }); self diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 61cf534095af9..1ab32220efae4 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1046,7 +1046,7 @@ where } impl<'tcx, T> Binder<'tcx, T> { - pub fn skip_binder_predicates(self) -> &'tcx List> { + pub fn skip_binder_predicates(&self) -> &'tcx List> { self.bound_predicates } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 066129d8e4731..d2e0a2dd73bc0 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -500,8 +500,13 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } } } else { - let kind = self.infcx.instantiate_binder_with_placeholders(kind); - let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); + let (kind, additional_assumptions) = + self.instantiate_binder_and_assumptions_with_placeholders(kind); + let goal = Goal::new( + self.tcx(), + ty::ParamEnv::augment(self.tcx(), goal.param_env, additional_assumptions), + ty::Binder::dummy(kind), + ); self.add_goal(goal); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } @@ -799,6 +804,19 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ) } + pub(super) fn instantiate_binder_and_predicates_with_infer< + T: TypeFoldable> + Copy, + >( + &self, + value: ty::Binder<'tcx, T>, + ) -> (T, &'tcx ty::List>) { + self.infcx.instantiate_binder_and_predicates_with_fresh_vars( + DUMMY_SP, + LateBoundRegionConversionTime::HigherRankedType, + value, + ) + } + pub(super) fn instantiate_binder_with_placeholders> + Copy>( &self, value: ty::Binder<'tcx, T>, @@ -806,6 +824,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { self.infcx.instantiate_binder_with_placeholders(value) } + pub(super) fn instantiate_binder_and_assumptions_with_placeholders< + T: TypeFoldable> + Copy, + >( + &self, + value: ty::Binder<'tcx, T>, + ) -> (T, &'tcx ty::List>) { + self.infcx.instantiate_binder_and_assumptions_with_placeholders(value) + } + pub(super) fn resolve_vars_if_possible(&self, value: T) -> T where T: TypeFoldable>, diff --git a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs index 4950a444ffb50..69d33842644d4 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs @@ -119,8 +119,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { if projection_pred.projection_def_id() == goal.predicate.def_id() { let tcx = ecx.tcx(); ecx.probe_misc_candidate("assumption").enter(|ecx| { - let assumption_projection_pred = - ecx.instantiate_binder_with_infer(projection_pred); + let (assumption_projection_pred, additional_goals) = + ecx.instantiate_binder_and_predicates_with_infer(projection_pred); ecx.eq( goal.param_env, goal.predicate.projection_ty, @@ -135,7 +135,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { .instantiate_own(tcx, goal.predicate.projection_ty.args) .map(|(pred, _)| goal.with(tcx, pred)), ); - + ecx.add_goals(additional_goals.iter().map(|pred| goal.with(tcx, pred))); then(ecx) }) } else { diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index fa91a125b6acc..cdb9d30d033a9 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -97,12 +97,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { { // FIXME: Constness ecx.probe_misc_candidate("assumption").enter(|ecx| { - let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); + let (assumption_trait_pred, additional_goals) = + ecx.instantiate_binder_and_predicates_with_infer(trait_clause); ecx.eq( goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref, )?; + let tcx = ecx.tcx(); + ecx.add_goals(additional_goals.iter().map(|pred| goal.with(tcx, pred))); then(ecx) }) } else { From 07f178c32c5127d595d29d2e80ce0e267a25fb3f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 3 Sep 2023 21:52:16 +0000 Subject: [PATCH 5/8] Support trait predicates on poly trait refs --- compiler/rustc_ast_lowering/src/lib.rs | 21 +++++++++++++++- compiler/rustc_hir/src/hir.rs | 3 +++ compiler/rustc_hir/src/intravisit.rs | 1 + .../rustc_hir_analysis/src/astconv/bounds.rs | 24 ++++++++++++------- .../src/astconv/object_safety.rs | 5 +++- .../src/collect/predicates_of.rs | 13 ++++++++-- .../src/collect/resolve_bound_vars.rs | 1 + compiler/rustc_hir_analysis/src/lib.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 16 ++++++++++--- 9 files changed, 70 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1e51449e70cc6..7b920f6221f83 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2115,10 +2115,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx: &ImplTraitContext, constness: ast::Const, ) -> hir::PolyTraitRef<'hir> { + let binder_predicates = + self.arena.alloc_from_iter(p.bound_generic_params.iter().filter_map(|param| { + self.lower_generic_bound_predicate( + param.ident, + param.id, + ¶m.kind, + ¶m.bounds, + param.colon_span, + p.span, + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + hir::PredicateOrigin::GenericParam, + ) + })); let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); let trait_ref = self.lower_trait_ref(constness, &p.trait_ref, itctx); - hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } + hir::PolyTraitRef { + bound_generic_params, + binder_predicates, + trait_ref, + span: self.lower_span(p.span), + } } fn lower_mt(&mut self, mt: &MutTy, itctx: &ImplTraitContext) -> hir::MutTy<'hir> { @@ -2425,6 +2443,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => { let principal = hir::PolyTraitRef { bound_generic_params: &[], + binder_predicates: &[], trait_ref: hir::TraitRef { path, hir_ref_id: hir_id }, span: self.lower_span(span), }; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 5911e3fee238b..5e25dc26602a3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3002,6 +3002,9 @@ pub struct PolyTraitRef<'hir> { /// The `'a` in `for<'a> Foo<&'a T>`. pub bound_generic_params: &'hir [GenericParam<'hir>], + /// Predicates on the `for` binder itself, such as `for ...` + pub binder_predicates: &'hir [WherePredicate<'hir>], + /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`. pub trait_ref: TraitRef<'hir>, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 0e86f19f8c106..9310de9430ce4 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1088,6 +1088,7 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericB pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v PolyTraitRef<'v>) { walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params); visitor.visit_trait_ref(&trait_ref.trait_ref); + walk_list!(visitor, visit_where_predicate, trait_ref.binder_predicates); } pub fn walk_struct_def<'v, V: Visitor<'v>>( diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index b99fbbc120c73..08c65393d98fe 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -18,8 +18,8 @@ use crate::errors; impl<'tcx> dyn AstConv<'tcx> + '_ { pub(crate) fn lower_where_predicates( &self, - params: &'tcx [hir::GenericParam<'tcx>], - hir_predicates: &'tcx [hir::WherePredicate<'tcx>], + params: &[hir::GenericParam<'_>], + hir_predicates: &[hir::WherePredicate<'_>], predicates: &mut FxIndexSet<(ty::Clause<'tcx>, Span)>, ) { // Collect the predicates that were written inline by the user on each @@ -140,19 +140,19 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { } /// Sets `implicitly_sized` to true on `Bounds` if necessary - pub(crate) fn add_implicitly_sized( + pub(crate) fn add_implicitly_sized<'hir>( &self, bounds: &mut Bounds<'tcx>, self_ty: Ty<'tcx>, - ast_bounds: &'tcx [hir::GenericBound<'tcx>], - self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + ast_bounds: &'hir [hir::GenericBound<'hir>], + self_ty_where_predicates: Option<(LocalDefId, &'hir [hir::WherePredicate<'hir>])>, span: Span, ) { let tcx = self.tcx(); // Try to find an unbound in bounds. let mut unbound = None; - let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| { + let mut search_bounds = |ast_bounds: &'hir [hir::GenericBound<'hir>]| { for ab in ast_bounds { if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab { if unbound.is_none() { @@ -244,8 +244,16 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { hir::TraitBoundModifier::Maybe => continue, }; - // TODO: Add in the binder preds from the poly trait ref. - let binder_predicates = binder_predicates; + let mut additional_binder_predicates = FxIndexSet::default(); + self.lower_where_predicates( + poly_trait_ref.bound_generic_params, + poly_trait_ref.binder_predicates, + &mut additional_binder_predicates, + ); + let binder_predicates = + self.tcx().mk_clauses_from_iter(binder_predicates.into_iter().chain( + additional_binder_predicates.into_iter().map(|(clause, _)| clause), + )); let _ = self.instantiate_poly_trait_ref( &poly_trait_ref.trait_ref, diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 3d8cc1cbaa15b..d73ce4f9ba2c3 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -34,6 +34,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut potential_assoc_types = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; for trait_bound in hir_trait_bounds.iter().rev() { + assert!( + trait_bound.binder_predicates.is_empty(), + "FIXME(non_lifetime_binders): object types should not have binders" + ); if let GenericArgCountResult { correct: Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }), @@ -46,7 +50,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { dummy_self, &mut bounds, false, - // TODO: dyn traits should have no binder preds ty::List::empty(), // FIXME: This should be `true`, but we don't really handle // associated type bounds or type aliases in objects in a way diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index e0a05b440e98d..a5f60db757332 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -712,6 +712,16 @@ impl<'tcx> ItemCtxt<'tcx> { } }; + let mut binder_predicates = FxIndexSet::default(); + self.astconv().lower_where_predicates( + predicate.bound_generic_params, + predicate.binder_predicates, + &mut binder_predicates, + ); + let binder_predicates = self + .tcx + .mk_clauses_from_iter(binder_predicates.into_iter().map(|(clause, _)| clause)); + // Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we // want to only consider predicates with `Self: ...`, but we don't want // `OnlySelfBounds(true)` since we want to collect the nested associated @@ -733,8 +743,7 @@ impl<'tcx> ItemCtxt<'tcx> { }), &mut bounds, bound_vars, - // TODO: convert `where_bound_predicate` above accordingly - ty::List::empty(), + binder_predicates, only_self_bounds, ); } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index bb1e2145b8b90..a666a684a8566 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -398,6 +398,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { self.with(scope, |this| { walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); this.visit_trait_ref(&trait_ref.trait_ref); + walk_list!(this, visit_where_predicate, trait_ref.binder_predicates); }); } } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index b643dc6eeaba6..11d50d6341c4a 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -265,7 +265,7 @@ pub fn hir_trait_to_predicates<'tcx>( self_ty, &mut bounds, true, - // TODO: This is probably wrong! + // FIXME(non_lifetime_binders): This is probably not right. ty::List::empty(), OnlySelfBounds(false), ); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ed1348ce324dc..29c4a85c96a68 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -821,18 +821,28 @@ impl<'tcx> Clause<'tcx> { let pred_bound_vars = bound_pred.bound_vars(); let trait_bound_vars = trait_ref.bound_vars(); // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> - let shifted_pred = - tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); + let (shifted_pred, shifted_bound_clauses) = tcx.shift_bound_var_indices( + trait_bound_vars.len(), + (bound_pred.skip_binder(), bound_pred.skip_binder_predicates()), + ); // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args); // 3) ['x] + ['b] -> ['x, 'b] let bound_vars = tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars)); + let binder_predicates = tcx.mk_clauses_from_iter( + trait_ref.skip_binder_predicates().into_iter().chain(shifted_bound_clauses), + ); + // FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here? tcx.reuse_or_mk_predicate( self.as_predicate(), - ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars), + ty::Binder::bind_with_vars_and_predicates( + PredicateKind::Clause(new), + bound_vars, + binder_predicates, + ), ) .expect_clause() } From b28571c3ed26d4f1529137b65e5a55b4847b2fa4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 17 Oct 2023 23:54:23 +0000 Subject: [PATCH 6/8] More work --- .../rustc_hir_analysis/src/astconv/bounds.rs | 15 +++- compiler/rustc_hir_typeck/src/method/probe.rs | 3 +- .../src/infer/higher_ranked/mod.rs | 8 ++- compiler/rustc_infer/src/infer/mod.rs | 7 +- .../rustc_infer/src/infer/nll_relate/mod.rs | 4 +- .../src/opaque_hidden_inferred_bound.rs | 4 +- compiler/rustc_middle/src/ty/context.rs | 1 + compiler/rustc_middle/src/ty/fold.rs | 3 +- compiler/rustc_middle/src/ty/mod.rs | 4 +- .../rustc_middle/src/ty/structural_impls.rs | 8 ++- compiler/rustc_middle/src/ty/sty.rs | 4 +- tests/ui/symbol-names/basic.legacy.stderr | 4 +- .../ui/symbol-names/issue-60925.legacy.stderr | 4 +- tests/ui/traits/cache-reached-depth-ice.rs | 2 +- .../ui/traits/cache-reached-depth-ice.stderr | 2 +- .../issue-83538-tainted-cache-after-cycle.rs | 8 +-- ...sue-83538-tainted-cache-after-cycle.stderr | 8 +-- .../traits/issue-85360-eval-obligation-ice.rs | 8 +-- .../issue-85360-eval-obligation-ice.stderr | 8 +-- .../non_lifetime_binders/bad-copy-cond.rs | 2 + .../non_lifetime_binders/bad-copy-cond.stderr | 6 +- .../non_lifetime_binders/bad-sized-cond.rs | 6 +- .../bad-sized-cond.stderr | 47 ++----------- tests/ui/traits/non_lifetime_binders/basic.rs | 4 +- .../traits/non_lifetime_binders/basic.stderr | 2 +- .../capture-late-ct-in-anon.rs | 2 + .../capture-late-ct-in-anon.stderr | 4 +- .../drop-impl-pred.no.stderr | 6 +- .../non_lifetime_binders/drop-impl-pred.rs | 1 + .../drop-impl-pred.yes.stderr | 2 +- tests/ui/traits/non_lifetime_binders/fail.rs | 2 + .../traits/non_lifetime_binders/fail.stderr | 12 ++-- .../foreach-partial-eq.rs | 2 + .../foreach-partial-eq.stderr | 6 +- .../late-bound-in-anon-ct.rs | 2 + .../late-bound-in-anon-ct.stderr | 6 +- .../non_lifetime_binders/method-probe.rs | 1 + .../non_lifetime_binders/method-probe.stderr | 2 +- .../missing-assoc-item.rs | 2 + .../missing-assoc-item.stderr | 4 +- .../nested-apit-mentioning-outer-bound-var.rs | 2 + ...ted-apit-mentioning-outer-bound-var.stderr | 4 +- .../object-lifetime-default-for-late.rs | 2 +- .../ui/traits/non_lifetime_binders/on-dyn.rs | 2 + .../traits/non_lifetime_binders/on-dyn.stderr | 4 +- .../ui/traits/non_lifetime_binders/on-ptr.rs | 2 + .../traits/non_lifetime_binders/on-ptr.stderr | 4 +- .../ui/traits/non_lifetime_binders/on-rpit.rs | 1 + .../non_lifetime_binders/on-rpit.stderr | 2 +- .../sized-late-bound-issue-114872.rs | 1 + .../sized-late-bound-issue-114872.stderr | 2 +- .../supertrait-object-safety.rs | 10 ++- .../supertrait-object-safety.stderr | 68 ++++++++++--------- .../type-match-with-late-bound.rs | 1 + .../type-match-with-late-bound.stderr | 2 +- .../non_lifetime_binders/universe-error1.rs | 2 + .../universe-error1.stderr | 6 +- tests/ui/traits/project-modulo-regions.rs | 4 +- .../project-modulo-regions.with_clause.stderr | 2 +- ...oject-modulo-regions.without_clause.stderr | 2 +- ...equality_in_canonical_query.current.stderr | 29 -------- 61 files changed, 187 insertions(+), 191 deletions(-) delete mode 100644 tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 08c65393d98fe..925dfcaa395b1 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -126,8 +126,17 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { } _ => bug!(), }; - let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)) - .to_predicate(self.tcx()); + let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)); + // This predicate may have escaping bound vars, e.g. if + // we have `for<'a: 'a> ..`. Since outlives predicates + // don't implicitly have a binder added for them in + // resolve_bound_vars, we need to explicitly shift the + // vars in once here. + let pred = ty::Binder::bind_with_vars( + ty::fold::shift_vars(self.tcx(), pred, 1), + ty::List::empty(), + ) + .to_predicate(self.tcx()); (pred, span) })) } @@ -715,7 +724,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { ast_bounds.iter(), bounds, projection_ty.bound_vars(), - projection_ty.skip_binder_predicates(), + projection_ty.skip_binder_with_predicates().1, only_self_bounds, ); } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 74f469cb39cbf..29d8de0b50535 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -851,7 +851,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }); self.elaborate_bounds(bounds, |this, poly_trait_ref, item| { - let trait_ref = this.instantiate_binder_with_fresh_vars( + // FIXME(non_lifetime_binders): We could check these predicates hold. + let (trait_ref, _) = this.instantiate_binder_and_predicates_with_fresh_vars( this.span, infer::LateBoundRegionConversionTime::FnCall, poly_trait_ref, diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index 7c693b67cda51..613b640f095f7 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -7,6 +7,7 @@ use crate::infer::CombinedSnapshot; use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Binder, Ty, TyCtxt, TypeFoldable}; +use rustc_span::DUMMY_SP; impl<'a, 'tcx> CombineFields<'a, 'tcx> { /// Checks whether `for<..> sub <: for<..> sup` holds. @@ -74,7 +75,12 @@ impl<'tcx> InferCtxt<'tcx> { where T: TypeFoldable> + Copy, { - assert_eq!(binder.skip_binder_predicates(), ty::List::empty()); + if !binder.skip_binder_with_predicates().1.is_empty() { + self.tcx.sess.delay_span_bug( + DUMMY_SP, + "binder instantiated with placeholders ignoring predicates", + ); + } if let Some(inner) = binder.no_bound_vars() { return inner; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b903dd00ce1f6..a334fd5d84482 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -9,6 +9,7 @@ pub use combine::ObligationEmittingRelation; use rustc_data_structures::captures::Captures; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; +use rustc_span::DUMMY_SP; use self::opaque_types::OpaqueTypeStorage; pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; @@ -1468,7 +1469,11 @@ impl<'tcx> InferCtxt<'tcx> { where T: TypeFoldable> + Copy, { - assert_eq!(value.skip_binder_predicates(), ty::List::empty()); + if !value.skip_binder_with_predicates().1.is_empty() { + self.tcx + .sess + .delay_span_bug(DUMMY_SP, "binder instantiated with infer ignoring predicates"); + } if let Some(inner) = value.no_bound_vars() { return inner; diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index d880e6bf991b0..7b7740633c660 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -263,7 +263,7 @@ where where T: ty::TypeFoldable> + Copy, { - assert_eq!(binder.skip_binder_predicates(), ty::List::empty()); + assert_eq!(binder.skip_binder_with_predicates().1, ty::List::empty()); if let Some(inner) = binder.no_bound_vars() { return inner; @@ -313,7 +313,7 @@ where where T: ty::TypeFoldable> + Copy, { - assert_eq!(binder.skip_binder_predicates(), ty::List::empty()); + assert_eq!(binder.skip_binder_with_predicates().1, ty::List::empty()); if let Some(inner) = binder.no_bound_vars() { return inner; diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index c24846ca93988..872d49293561f 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -77,7 +77,9 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { for (pred, pred_span) in cx.tcx.explicit_item_bounds(def_id).instantiate_identity_iter_copied() { - let predicate = infcx.instantiate_binder_with_placeholders(pred.kind()); + // FIXME(non_lifetime_binders): We could assume the predicates in this binder. + let (predicate, _) = + infcx.instantiate_binder_and_assumptions_with_placeholders(pred.kind()); let ty::ClauseKind::Projection(proj) = predicate else { continue; }; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 6a9a8bcdc0677..7cee639ce4922 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1296,6 +1296,7 @@ nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>} nop_lift! {predicate; Clause<'a> => Clause<'tcx>} nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>} +nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>} nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>} nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind} diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 900360ca7dc21..e7ea3c0d1b8e5 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -322,8 +322,7 @@ impl<'tcx> TyCtxt<'tcx> { value: Binder<'tcx, T>, delegate: impl BoundVarReplacerDelegate<'tcx>, ) -> (T, &'tcx ty::List>) { - let preds = value.skip_binder_predicates(); - self.replace_escaping_bound_vars_uncached((value.skip_binder(), preds), delegate) + self.replace_escaping_bound_vars_uncached(value.skip_binder_with_predicates(), delegate) } /// Replaces any late-bound regions bound in `value` with diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 29c4a85c96a68..ba8624554f259 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -823,7 +823,7 @@ impl<'tcx> Clause<'tcx> { // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> let (shifted_pred, shifted_bound_clauses) = tcx.shift_bound_var_indices( trait_bound_vars.len(), - (bound_pred.skip_binder(), bound_pred.skip_binder_predicates()), + bound_pred.skip_binder_with_predicates(), ); // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args); @@ -832,7 +832,7 @@ impl<'tcx> Clause<'tcx> { tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars)); let binder_predicates = tcx.mk_clauses_from_iter( - trait_ref.skip_binder_predicates().into_iter().chain(shifted_bound_clauses), + trait_ref.skip_binder_with_predicates().1.into_iter().chain(shifted_bound_clauses), ); // FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here? diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 7f86acd4bf5b1..1e6c98652ba31 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -532,7 +532,9 @@ impl<'tcx, T: TypeFoldable>> TypeSuperFoldable> for ty self, folder: &mut F, ) -> Result { - self.try_map_bound(|ty| ty.try_fold_with(folder)) + let bound_vars = self.bound_vars(); + let (value, bound_predicates) = self.skip_binder_with_predicates().try_fold_with(folder)?; + Ok(ty::Binder::bind_with_vars_and_predicates(value, bound_vars, bound_predicates)) } } @@ -543,7 +545,9 @@ impl<'tcx, T: TypeVisitable>> TypeSuperVisitable> &self, visitor: &mut V, ) -> ControlFlow { - self.as_ref().skip_binder().visit_with(visitor) + let (val, predicates) = self.as_ref().skip_binder_with_predicates(); + val.visit_with(visitor)?; + predicates.visit_with(visitor) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 1ab32220efae4..9d9326dfce589 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1046,8 +1046,8 @@ where } impl<'tcx, T> Binder<'tcx, T> { - pub fn skip_binder_predicates(&self) -> &'tcx List> { - self.bound_predicates + pub fn skip_binder_with_predicates(self) -> (T, &'tcx List>) { + (self.value, self.bound_predicates) } /// Skips the binder and returns the "bound" value. This is a diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr index 61d27ec69f4d2..9c5dc1fda8b41 100644 --- a/tests/ui/symbol-names/basic.legacy.stderr +++ b/tests/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17h9308686d0228fa1dE) +error: symbol-name(_ZN5basic4main17h96b56acaf300ea6eE) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::h9308686d0228fa1d) +error: demangling(basic::main::h96b56acaf300ea6e) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr index eb65f3b58fff8..931580ecebc98 100644 --- a/tests/ui/symbol-names/issue-60925.legacy.stderr +++ b/tests/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h84ab5dafbd2a1508E) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h46eaa20e0d673fbeE) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h84ab5dafbd2a1508) +error: demangling(issue_60925::foo::Foo::foo::h46eaa20e0d673fbe) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/tests/ui/traits/cache-reached-depth-ice.rs b/tests/ui/traits/cache-reached-depth-ice.rs index 8c2391113d719..85f725840b411 100644 --- a/tests/ui/traits/cache-reached-depth-ice.rs +++ b/tests/ui/traits/cache-reached-depth-ice.rs @@ -41,5 +41,5 @@ fn test() {} fn main() { test::(); - //~^ ERROR evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) + //~^ ERROR evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOk) } diff --git a/tests/ui/traits/cache-reached-depth-ice.stderr b/tests/ui/traits/cache-reached-depth-ice.stderr index 7cd75819277df..575c92f50c795 100644 --- a/tests/ui/traits/cache-reached-depth-ice.stderr +++ b/tests/ui/traits/cache-reached-depth-ice.stderr @@ -1,4 +1,4 @@ -error: evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) +error: evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOk) --> $DIR/cache-reached-depth-ice.rs:43:5 | LL | fn test() {} diff --git a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs index 5136aef4f7aa7..a27aba443bb67 100644 --- a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs +++ b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs @@ -57,10 +57,10 @@ fn main() { // Key is that Vec is "ok" and Third<'_, Ty> is "ok modulo regions": forward(); - //~^ ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) + //~^ ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOkModuloRegions) reverse(); - //~^ ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) + //~^ ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOkModuloRegions) } diff --git a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr index 96baec76a17ec..3a25664667e7f 100644 --- a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr +++ b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr @@ -1,4 +1,4 @@ -error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) +error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOk) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5 | LL | Vec: Unpin, @@ -7,7 +7,7 @@ LL | Vec: Unpin, LL | forward(); | ^^^^^^^ -error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5 | LL | Third<'a, Ty>: Unpin, @@ -16,7 +16,7 @@ LL | Third<'a, Ty>: Unpin, LL | forward(); | ^^^^^^^ -error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5 | LL | Third<'a, Ty>: Unpin, @@ -25,7 +25,7 @@ LL | Third<'a, Ty>: Unpin, LL | reverse(); | ^^^^^^^ -error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) +error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOk) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5 | LL | Vec: Unpin, diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.rs b/tests/ui/traits/issue-85360-eval-obligation-ice.rs index ac8bda9c01042..c0e97ed8c4a28 100644 --- a/tests/ui/traits/issue-85360-eval-obligation-ice.rs +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.rs @@ -7,12 +7,12 @@ use core::marker::PhantomData; fn main() { test::>>(make()); - //~^ ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) + //~^ ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOk) test::>>(make()); - //~^ ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) - //~| ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) + //~^ ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOkModuloRegions) + //~| ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOkModuloRegions) } #[rustc_evaluate_where_clauses] diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.stderr b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr index 9590ea12c05e4..11a975f647754 100644 --- a/tests/ui/traits/issue-85360-eval-obligation-ice.stderr +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr @@ -1,4 +1,4 @@ -error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) +error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOk) --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 | LL | test::>>(make()); @@ -7,7 +7,7 @@ LL | test::>>(make()); LL | fn test(_: T) {} | - predicate -error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) +error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOk) --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 | LL | test::>>(make()); @@ -16,7 +16,7 @@ LL | test::>>(make()); LL | fn test(_: T) {} | ----- predicate -error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-85360-eval-obligation-ice.rs:13:5 | LL | test::>>(make()); @@ -25,7 +25,7 @@ LL | test::>>(make()); LL | fn test(_: T) {} | - predicate -error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-85360-eval-obligation-ice.rs:13:5 | LL | test::>>(make()); diff --git a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.rs b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.rs index 506cad25f630c..26baafc37d198 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.rs +++ b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + #![feature(non_lifetime_binders)] //~^ WARN the feature `non_lifetime_binders` is incomplete diff --git a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr index 07e02d47f27f6..faba37f04546c 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr +++ b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/bad-copy-cond.rs:1:12 + --> $DIR/bad-copy-cond.rs:3:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,13 +8,13 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/bad-copy-cond.rs:7:5 + --> $DIR/bad-copy-cond.rs:9:5 | LL | foo(); | ^^^ the trait `Copy` is not implemented for `T` | note: required by a bound in `foo` - --> $DIR/bad-copy-cond.rs:4:26 + --> $DIR/bad-copy-cond.rs:6:26 | LL | fn foo() where for T: Copy {} | ^^^^ required by this bound in `foo` diff --git a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.rs b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.rs index dfc800c8e7e12..c61cb73cef870 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.rs +++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + #![feature(non_lifetime_binders)] //~^ WARN is incomplete and may not be safe @@ -15,9 +17,7 @@ where fn main() { foo(); - //~^ ERROR the size for values of type `V` cannot be known at compilation time bar(); - //~^ ERROR the size for values of type `V` cannot be known at compilation time - //~| ERROR `V` is not an iterator + //~^ ERROR the trait bound `V: IntoIterator` is not satisfied } diff --git a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr index d8db07277c500..fba9d24f649b8 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr +++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/bad-sized-cond.rs:1:12 + --> $DIR/bad-sized-cond.rs:3:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -7,49 +7,14 @@ LL | #![feature(non_lifetime_binders)] = note: see issue #108185 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: the size for values of type `V` cannot be known at compilation time - --> $DIR/bad-sized-cond.rs:17:5 - | -LL | foo(); - | ^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `V` -note: required by a bound in `foo` - --> $DIR/bad-sized-cond.rs:6:15 - | -LL | pub fn foo() - | --- required by a bound in this function -LL | where -LL | for V: Sized, - | ^^^^^ required by this bound in `foo` - -error[E0277]: `V` is not an iterator - --> $DIR/bad-sized-cond.rs:20:5 - | -LL | bar(); - | ^^^ `V` is not an iterator - | - = help: the trait `Iterator` is not implemented for `V` - = note: required for `V` to implement `IntoIterator` -note: required by a bound in `bar` - --> $DIR/bad-sized-cond.rs:12:15 - | -LL | pub fn bar() - | --- required by a bound in this function -LL | where -LL | for V: IntoIterator, - | ^^^^^^^^^^^^ required by this bound in `bar` - -error[E0277]: the size for values of type `V` cannot be known at compilation time - --> $DIR/bad-sized-cond.rs:20:5 +error[E0277]: the trait bound `V: IntoIterator` is not satisfied + --> $DIR/bad-sized-cond.rs:21:5 | LL | bar(); - | ^^^ doesn't have a size known at compile-time + | ^^^ the trait `IntoIterator` is not implemented for `V` | - = help: the trait `Sized` is not implemented for `V` - = note: required for `V` to implement `IntoIterator` note: required by a bound in `bar` - --> $DIR/bad-sized-cond.rs:12:15 + --> $DIR/bad-sized-cond.rs:14:15 | LL | pub fn bar() | --- required by a bound in this function @@ -57,6 +22,6 @@ LL | where LL | for V: IntoIterator, | ^^^^^^^^^^^^ required by this bound in `bar` -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non_lifetime_binders/basic.rs b/tests/ui/traits/non_lifetime_binders/basic.rs index a797aae65dba2..c329ecbdcdb1d 100644 --- a/tests/ui/traits/non_lifetime_binders/basic.rs +++ b/tests/ui/traits/non_lifetime_binders/basic.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + // check-pass // Basic test that show's we can succesfully typeck a `for` where clause. @@ -6,7 +8,7 @@ trait Trait {} -impl Trait for T {} +impl Trait for T {} fn foo() where diff --git a/tests/ui/traits/non_lifetime_binders/basic.stderr b/tests/ui/traits/non_lifetime_binders/basic.stderr index 0fd16c5d0ee04..82bf69057528e 100644 --- a/tests/ui/traits/non_lifetime_binders/basic.stderr +++ b/tests/ui/traits/non_lifetime_binders/basic.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/basic.rs:4:12 + --> $DIR/basic.rs:6:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.rs b/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.rs index bbae67f0bad41..14aa8da557aeb 100644 --- a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.rs +++ b/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + #![feature(non_lifetime_binders)] //~^ WARN the feature `non_lifetime_binders` is incomplete diff --git a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr b/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr index d65892ec6dffb..563443a10f393 100644 --- a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr +++ b/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-late-ct-in-anon.rs:1:12 + --> $DIR/capture-late-ct-in-anon.rs:3:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error: cannot capture late-bound const parameter in constant - --> $DIR/capture-late-ct-in-anon.rs:6:30 + --> $DIR/capture-late-ct-in-anon.rs:8:30 | LL | for [(); C]: Copy, | -------------- ^ diff --git a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr index a985b1a6e12f6..9de485acd04ef 100644 --- a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr +++ b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/drop-impl-pred.rs:6:12 + --> $DIR/drop-impl-pred.rs:7:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,13 +8,13 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error[E0367]: `Drop` impl requires `H: Foo` but the struct it is implemented for does not - --> $DIR/drop-impl-pred.rs:19:15 + --> $DIR/drop-impl-pred.rs:20:15 | LL | for H: Foo, | ^^^ | note: the implementor must specify the same requirement - --> $DIR/drop-impl-pred.rs:12:1 + --> $DIR/drop-impl-pred.rs:13:1 | LL | struct Bar(T) where T: Foo; | ^^^^^^^^^^^^^ diff --git a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs index c65b5ea9ba493..a79c619725106 100644 --- a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs +++ b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs @@ -1,3 +1,4 @@ +// compile-flags: -Ztrait-solver=next // revisions: no yes //[yes] check-pass diff --git a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.yes.stderr b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.yes.stderr index 165cf2ee13da8..adcb5cfaae580 100644 --- a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.yes.stderr +++ b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.yes.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/drop-impl-pred.rs:6:12 + --> $DIR/drop-impl-pred.rs:7:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/non_lifetime_binders/fail.rs b/tests/ui/traits/non_lifetime_binders/fail.rs index 460f68907e889..7ab7d4b469223 100644 --- a/tests/ui/traits/non_lifetime_binders/fail.rs +++ b/tests/ui/traits/non_lifetime_binders/fail.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + // Error reporting for where `for T: Trait` doesn't hold #![feature(non_lifetime_binders)] diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr index 240bcef7df504..46c5913985ad5 100644 --- a/tests/ui/traits/non_lifetime_binders/fail.stderr +++ b/tests/ui/traits/non_lifetime_binders/fail.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/fail.rs:3:12 + --> $DIR/fail.rs:5:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,18 +8,18 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: the trait bound `T: Trait` is not satisfied - --> $DIR/fail.rs:19:5 + --> $DIR/fail.rs:21:5 | LL | fail(); | ^^^^ the trait `Trait` is not implemented for `T` | help: this trait has no implementations, consider adding one - --> $DIR/fail.rs:6:1 + --> $DIR/fail.rs:8:1 | LL | trait Trait {} | ^^^^^^^^^^^ note: required by a bound in `fail` - --> $DIR/fail.rs:10:15 + --> $DIR/fail.rs:12:15 | LL | fn fail() | ---- required by a bound in this function @@ -28,14 +28,14 @@ LL | for T: Trait, | ^^^^^ required by this bound in `fail` error[E0277]: `T` cannot be sent between threads safely - --> $DIR/fail.rs:21:5 + --> $DIR/fail.rs:23:5 | LL | auto_trait(); | ^^^^^^^^^^ `T` cannot be sent between threads safely | = help: the trait `Send` is not implemented for `T` note: required by a bound in `auto_trait` - --> $DIR/fail.rs:15:15 + --> $DIR/fail.rs:17:15 | LL | fn auto_trait() | ---------- required by a bound in this function diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs index 96a7424f0dc9c..bb55b58b0fd97 100644 --- a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs +++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + #![feature(non_lifetime_binders)] //~^ WARN the feature `non_lifetime_binders` is incomplete diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr index da09343fb276b..a7408aeeb1d6d 100644 --- a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr +++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/foreach-partial-eq.rs:1:12 + --> $DIR/foreach-partial-eq.rs:3:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,14 +8,14 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: can't compare `T` with `T` - --> $DIR/foreach-partial-eq.rs:10:5 + --> $DIR/foreach-partial-eq.rs:12:5 | LL | auto_trait(); | ^^^^^^^^^^ no implementation for `T < T` and `T > T` | = help: the trait `PartialOrd` is not implemented for `T` note: required by a bound in `auto_trait` - --> $DIR/foreach-partial-eq.rs:6:27 + --> $DIR/foreach-partial-eq.rs:8:27 | LL | fn auto_trait() | ---------- required by a bound in this function diff --git a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs index 64f09f823fc29..6f8175258ebff 100644 --- a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs +++ b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + #![feature(non_lifetime_binders, generic_const_exprs)] //~^ WARN the feature `non_lifetime_binders` is incomplete //~| WARN the feature `generic_const_exprs` is incomplete diff --git a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr index dc54e1acc392c..3a8c97c40b1c3 100644 --- a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr +++ b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/late-bound-in-anon-ct.rs:1:12 + --> $DIR/late-bound-in-anon-ct.rs:3:12 | LL | #![feature(non_lifetime_binders, generic_const_exprs)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![feature(non_lifetime_binders, generic_const_exprs)] = note: `#[warn(incomplete_features)]` on by default warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/late-bound-in-anon-ct.rs:1:34 + --> $DIR/late-bound-in-anon-ct.rs:3:34 | LL | #![feature(non_lifetime_binders, generic_const_exprs)] | ^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | #![feature(non_lifetime_binders, generic_const_exprs)] = note: see issue #76560 for more information error: cannot capture late-bound type parameter in constant - --> $DIR/late-bound-in-anon-ct.rs:7:27 + --> $DIR/late-bound-in-anon-ct.rs:9:27 | LL | for [i32; { let _: T = todo!(); 0 }]:, | - ^ diff --git a/tests/ui/traits/non_lifetime_binders/method-probe.rs b/tests/ui/traits/non_lifetime_binders/method-probe.rs index 8df240c2082b7..cc51bc1789cd4 100644 --- a/tests/ui/traits/non_lifetime_binders/method-probe.rs +++ b/tests/ui/traits/non_lifetime_binders/method-probe.rs @@ -1,3 +1,4 @@ +// compile-flags: -Ztrait-solver=next // check-pass #![feature(non_lifetime_binders)] diff --git a/tests/ui/traits/non_lifetime_binders/method-probe.stderr b/tests/ui/traits/non_lifetime_binders/method-probe.stderr index 8f61792e6ce7f..01c99955b9f22 100644 --- a/tests/ui/traits/non_lifetime_binders/method-probe.stderr +++ b/tests/ui/traits/non_lifetime_binders/method-probe.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/method-probe.rs:3:12 + --> $DIR/method-probe.rs:4:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs index 50f0152e904f4..ff87a217b6f4d 100644 --- a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs +++ b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + #![feature(non_lifetime_binders)] //~^ WARN the feature `non_lifetime_binders` is incomplete diff --git a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr index d985386423d29..e6a020210f12f 100644 --- a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr +++ b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/missing-assoc-item.rs:1:12 + --> $DIR/missing-assoc-item.rs:3:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error[E0223]: ambiguous associated type - --> $DIR/missing-assoc-item.rs:6:12 + --> $DIR/missing-assoc-item.rs:8:12 | LL | for B::Item: Send, | ^^^^^^^ diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs index e9ae00df7a09e..e1c1034701c7b 100644 --- a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs +++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + #![feature(non_lifetime_binders)] //~^ WARN the feature `non_lifetime_binders` is incomplete diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr index 1124076c23c9c..0460f3e33604f 100644 --- a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr +++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/nested-apit-mentioning-outer-bound-var.rs:1:12 + --> $DIR/nested-apit-mentioning-outer-bound-var.rs:3:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error: `impl Trait` can only mention type parameters from an fn or impl - --> $DIR/nested-apit-mentioning-outer-bound-var.rs:8:52 + --> $DIR/nested-apit-mentioning-outer-bound-var.rs:10:52 | LL | fn uwu(_: impl for Trait<(), Assoc = impl Trait>) {} | - type parameter declared here ^ diff --git a/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs index 9830241c3770c..864c45bb78fd5 100644 --- a/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs +++ b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: --crate-type=lib +// compile-flags: --crate-type=lib -Ztrait-solver=next #![feature(non_lifetime_binders)] //~^ WARN the feature `non_lifetime_binders` is incomplete diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.rs b/tests/ui/traits/non_lifetime_binders/on-dyn.rs index 8fb7dd27605f9..0654cb59a0259 100644 --- a/tests/ui/traits/non_lifetime_binders/on-dyn.rs +++ b/tests/ui/traits/non_lifetime_binders/on-dyn.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + // Tests to make sure that we reject polymorphic dyn trait. #![feature(non_lifetime_binders)] diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr index 95656f99976ff..1b2069b33aa8e 100644 --- a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr +++ b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/on-dyn.rs:3:12 + --> $DIR/on-dyn.rs:5:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error: late-bound type parameter not allowed on trait object types - --> $DIR/on-dyn.rs:8:30 + --> $DIR/on-dyn.rs:10:30 | LL | fn foo() -> &'static dyn for Test { | ^ diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.rs b/tests/ui/traits/non_lifetime_binders/on-ptr.rs index 0aaff52b6d8cd..98ba2709b3b0e 100644 --- a/tests/ui/traits/non_lifetime_binders/on-ptr.rs +++ b/tests/ui/traits/non_lifetime_binders/on-ptr.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + // Tests to make sure that we reject polymorphic fn ptrs. #![feature(non_lifetime_binders)] diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr index 3b17f7697b2be..7ad0d13cec9d8 100644 --- a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr +++ b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/on-ptr.rs:3:12 + --> $DIR/on-ptr.rs:5:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error: late-bound type parameter not allowed on function pointer types - --> $DIR/on-ptr.rs:6:17 + --> $DIR/on-ptr.rs:8:17 | LL | fn foo() -> for fn(T) { | ^ diff --git a/tests/ui/traits/non_lifetime_binders/on-rpit.rs b/tests/ui/traits/non_lifetime_binders/on-rpit.rs index c501e057e2830..0a1e5159a370e 100644 --- a/tests/ui/traits/non_lifetime_binders/on-rpit.rs +++ b/tests/ui/traits/non_lifetime_binders/on-rpit.rs @@ -1,3 +1,4 @@ +// compile-flags: -Ztrait-solver=next // check-pass #![feature(non_lifetime_binders)] diff --git a/tests/ui/traits/non_lifetime_binders/on-rpit.stderr b/tests/ui/traits/non_lifetime_binders/on-rpit.stderr index 34c56068c5cc5..c8396c3854844 100644 --- a/tests/ui/traits/non_lifetime_binders/on-rpit.stderr +++ b/tests/ui/traits/non_lifetime_binders/on-rpit.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/on-rpit.rs:3:12 + --> $DIR/on-rpit.rs:4:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.rs b/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.rs index ba55ab0718521..8d696e4b4a3d2 100644 --- a/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.rs +++ b/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.rs @@ -1,3 +1,4 @@ +// compile-flags: -Ztrait-solver=next // check-pass #![feature(non_lifetime_binders)] diff --git a/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.stderr b/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.stderr index e75d81270529e..33ea8eddd1160 100644 --- a/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.stderr +++ b/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/sized-late-bound-issue-114872.rs:3:12 + --> $DIR/sized-late-bound-issue-114872.rs:4:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.rs b/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.rs index a635edb4485bd..4504a82b318ce 100644 --- a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.rs +++ b/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + #![feature(non_lifetime_binders)] //~^ WARN the feature `non_lifetime_binders` is incomplete @@ -17,8 +19,10 @@ impl Bar for () {} fn main() { let x: &dyn Foo = &(); - //~^ ERROR the trait `Foo` cannot be made into an object - //~| ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the type `&dyn Foo` is not well-formed + //~| ERROR mismatched types needs_bar(x); - //~^ ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the type `&dyn Foo` is not well-formed + //~| ERROR the type `dyn Foo` is not well-formed + //~| ERROR the trait bound `dyn Foo: Bar` is not satisfied } diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr b/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr index d56519223f4da..73ba56c3a4337 100644 --- a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr +++ b/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/supertrait-object-safety.rs:1:12 + --> $DIR/supertrait-object-safety.rs:3:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -7,49 +7,51 @@ LL | #![feature(non_lifetime_binders)] = note: see issue #108185 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/supertrait-object-safety.rs:19:23 +error[E0308]: mismatched types + --> $DIR/supertrait-object-safety.rs:21:23 | LL | let x: &dyn Foo = &(); - | ^^^ `Foo` cannot be made into an object + | -------- ^^^ expected `&dyn Foo`, found `&()` + | | + | expected due to this | -note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/supertrait-object-safety.rs:4:12 - | -LL | trait Foo: for Bar {} - | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables - | | - | this trait cannot be made into an object... - = note: required for the cast from `&()` to `&dyn Foo` + = note: expected reference `&dyn Foo` + found reference `&()` -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/supertrait-object-safety.rs:19:12 +error: the type `&dyn Foo` is not well-formed + --> $DIR/supertrait-object-safety.rs:21:12 | LL | let x: &dyn Foo = &(); - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^ + +error[E0277]: the trait bound `dyn Foo: Bar` is not satisfied + --> $DIR/supertrait-object-safety.rs:24:15 + | +LL | needs_bar(x); + | --------- ^ the trait `Bar` is not implemented for `dyn Foo` + | | + | required by a bound introduced by this call | -note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/supertrait-object-safety.rs:4:12 + = help: the trait `Bar` is implemented for `()` +note: required by a bound in `needs_bar` + --> $DIR/supertrait-object-safety.rs:12:24 | -LL | trait Foo: for Bar {} - | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables - | | - | this trait cannot be made into an object... +LL | fn needs_bar(x: &(impl Bar + ?Sized)) { + | ^^^^^^^^ required by this bound in `needs_bar` -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/supertrait-object-safety.rs:22:5 +error: the type `dyn Foo` is not well-formed + --> $DIR/supertrait-object-safety.rs:24:5 | LL | needs_bar(x); - | ^^^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/supertrait-object-safety.rs:4:12 + | ^^^^^^^^^ + +error: the type `&dyn Foo` is not well-formed + --> $DIR/supertrait-object-safety.rs:24:15 | -LL | trait Foo: for Bar {} - | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables - | | - | this trait cannot be made into an object... +LL | needs_bar(x); + | ^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 5 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0038`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs index 5ff7089b993a8..a8497518a4d49 100644 --- a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs +++ b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs @@ -1,3 +1,4 @@ +// compile-flags: -Ztrait-solver=next // edition:2021 // check-pass diff --git a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr index 3609bed28dffb..f5f2e1e342178 100644 --- a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr +++ b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/type-match-with-late-bound.rs:6:12 + --> $DIR/type-match-with-late-bound.rs:7:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.rs b/tests/ui/traits/non_lifetime_binders/universe-error1.rs index eadee6b711e52..28f7e6985b53a 100644 --- a/tests/ui/traits/non_lifetime_binders/universe-error1.rs +++ b/tests/ui/traits/non_lifetime_binders/universe-error1.rs @@ -1,3 +1,5 @@ +// compile-flags: -Ztrait-solver=next + #![feature(non_lifetime_binders)] //~^ WARN the feature `non_lifetime_binders` is incomplete diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.stderr b/tests/ui/traits/non_lifetime_binders/universe-error1.stderr index bfcad72e35278..6bbcdb5adb10c 100644 --- a/tests/ui/traits/non_lifetime_binders/universe-error1.stderr +++ b/tests/ui/traits/non_lifetime_binders/universe-error1.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/universe-error1.rs:1:12 + --> $DIR/universe-error1.rs:3:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,13 +8,13 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: the trait bound `T: Other<_>` is not satisfied - --> $DIR/universe-error1.rs:14:11 + --> $DIR/universe-error1.rs:16:11 | LL | foo::<_>(); | ^ the trait `Other<_>` is not implemented for `T` | note: required by a bound in `foo` - --> $DIR/universe-error1.rs:11:15 + --> $DIR/universe-error1.rs:13:15 | LL | fn foo() | --- required by a bound in this function diff --git a/tests/ui/traits/project-modulo-regions.rs b/tests/ui/traits/project-modulo-regions.rs index e88f21ecfe801..4c580481dcad1 100644 --- a/tests/ui/traits/project-modulo-regions.rs +++ b/tests/ui/traits/project-modulo-regions.rs @@ -48,8 +48,8 @@ fn test(val: MyStruct) where Helper: HelperTrait { fn foo(val: MyStruct) { test(val); - //[with_clause]~^ ERROR evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) - //[without_clause]~^^ ERROR evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) + //[with_clause]~^ ERROR evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOkModuloRegions) + //[without_clause]~^^ ERROR evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOk) } fn main() {} diff --git a/tests/ui/traits/project-modulo-regions.with_clause.stderr b/tests/ui/traits/project-modulo-regions.with_clause.stderr index dcc98e855d1b4..3f34b5160b015 100644 --- a/tests/ui/traits/project-modulo-regions.with_clause.stderr +++ b/tests/ui/traits/project-modulo-regions.with_clause.stderr @@ -1,4 +1,4 @@ -error: evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOkModuloRegions) --> $DIR/project-modulo-regions.rs:50:5 | LL | fn test(val: MyStruct) where Helper: HelperTrait { diff --git a/tests/ui/traits/project-modulo-regions.without_clause.stderr b/tests/ui/traits/project-modulo-regions.without_clause.stderr index e9959567e06af..79f2821d495df 100644 --- a/tests/ui/traits/project-modulo-regions.without_clause.stderr +++ b/tests/ui/traits/project-modulo-regions.without_clause.stderr @@ -1,4 +1,4 @@ -error: evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) +error: evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], bound_predicates: [] }) = Ok(EvaluatedToOk) --> $DIR/project-modulo-regions.rs:50:5 | LL | fn test(val: MyStruct) where Helper: HelperTrait { diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr deleted file mode 100644 index 844103d77a8ce..0000000000000 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error: internal compiler error: no errors encountered even though `delay_span_bug` issued - -error: internal compiler error: {OpaqueTypeKey { def_id: DefId(get_rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }) } }} - | - = - - -error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(get_rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }))), bound_vars: [] } } } - --> $DIR/rpit_tait_equality_in_canonical_query.rs:28:5 - | -LL | query(get_rpit); - | ^^^^^^^^^^^^^^^ - | - - --> $DIR/rpit_tait_equality_in_canonical_query.rs:28:5 - | -LL | query(get_rpit); - | ^^^^^^^^^^^^^^^ - - - - - - - -query stack during panic: -end of query stack -error: aborting due to 3 previous errors - From 7960165d799b21cbc04910eca3f2615be405bc21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 19 Oct 2023 05:34:06 +0200 Subject: [PATCH 7/8] [hack] make it compile on my machine --- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_middle/src/query/plumbing.rs | 54 ++++++++++----------- compiler/rustc_middle/src/traits/mod.rs | 2 +- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 5e25dc26602a3..33d8997fa9cdc 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4094,7 +4094,7 @@ mod size_asserts { static_assert_size!(ForeignItem<'_>, 72); static_assert_size!(ForeignItemKind<'_>, 40); static_assert_size!(GenericArg<'_>, 32); - static_assert_size!(GenericBound<'_>, 48); + static_assert_size!(GenericBound<'_>, 64); static_assert_size!(Generics<'_>, 56); static_assert_size!(Impl<'_>, 80); static_assert_size!(ImplItem<'_>, 88); diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index f4a8ada8f685e..84157e1175a4c 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -338,33 +338,33 @@ macro_rules! define_callbacks { <$($K)* as keys::Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>> >::Cache; - // Ensure that keys grow no larger than 64 bytes - #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] - const _: () = { - if mem::size_of::>() > 64 { - panic!("{}", concat!( - "the query `", - stringify!($name), - "` has a key type `", - stringify!($($K)*), - "` that is too large" - )); - } - }; - - // Ensure that values grow no larger than 64 bytes - #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] - const _: () = { - if mem::size_of::>() > 64 { - panic!("{}", concat!( - "the query `", - stringify!($name), - "` has a value type `", - stringify!($V), - "` that is too large" - )); - } - }; + // // Ensure that keys grow no larger than 64 bytes + // #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] + // const _: () = { + // if mem::size_of::>() > 64 { + // panic!("{}", concat!( + // "the query `", + // stringify!($name), + // "` has a key type `", + // stringify!($($K)*), + // "` that is too large" + // )); + // } + // }; + + // // Ensure that values grow no larger than 64 bytes + // #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] + // const _: () = { + // if mem::size_of::>() > 64 { + // panic!("{}", concat!( + // "the query `", + // stringify!($name), + // "` has a value type `", + // stringify!($V), + // "` that is too large" + // )); + // } + // }; })* } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 9e2ff3820af64..d2a36993119c6 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -523,7 +523,7 @@ impl<'tcx> ObligationCauseCode<'tcx> { // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(ObligationCauseCode<'_>, 48); +static_assert_size!(ObligationCauseCode<'_>, 56); #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum StatementAsExpression { From d243a700b3473698937c9cbd0264af4937a9d292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 26 Oct 2023 14:49:47 +0200 Subject: [PATCH 8/8] rebase fixups --- compiler/rustc_infer/src/infer/mod.rs | 1 - compiler/rustc_middle/src/ty/mod.rs | 94 +------------ compiler/rustc_type_ir/src/predicate_kind.rs | 140 +++++++++++++++++++ 3 files changed, 141 insertions(+), 94 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index a334fd5d84482..dd90f76882917 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -9,7 +9,6 @@ pub use combine::ObligationEmittingRelation; use rustc_data_structures::captures::Captures; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; -use rustc_span::DUMMY_SP; use self::opaque_types::OpaqueTypeStorage; pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ba8624554f259..1090768092739 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -97,7 +97,7 @@ pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::BoundRegionKind::*; pub use self::sty::{ AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, - BoundVariableKind, CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, ConstKind, + BoundVariableKind, CanonicalPolyFnSig, ClauseKind, ClosureArgs, ClosureArgsParts, ConstKind, ConstVid, CoroutineArgs, CoroutineArgsParts, EarlyBoundRegion, EffectVid, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection, @@ -626,98 +626,6 @@ impl<'tcx> Clause<'tcx> { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)] -/// A clause is something that can appear in where bounds or be inferred -/// by implied bounds. -pub enum ClauseKind<'tcx> { - /// Corresponds to `where Foo: Bar`. `Foo` here would be - /// the `Self` type of the trait reference and `A`, `B`, and `C` - /// would be the type parameters. - Trait(TraitPredicate<'tcx>), - - /// `where 'a: 'b` - RegionOutlives(RegionOutlivesPredicate<'tcx>), - - /// `where T: 'a` - TypeOutlives(TypeOutlivesPredicate<'tcx>), - - /// `where ::Name == X`, approximately. - /// See the `ProjectionPredicate` struct for details. - Projection(ProjectionPredicate<'tcx>), - - /// Ensures that a const generic argument to a parameter `const N: u8` - /// is of type `u8`. - ConstArgHasType(Const<'tcx>, Ty<'tcx>), - - /// No syntax: `T` well-formed. - WellFormed(GenericArg<'tcx>), - - /// Constant initializer must evaluate successfully. - ConstEvaluatable(ty::Const<'tcx>), -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)] -pub enum PredicateKind<'tcx> { - /// Prove a clause - Clause(ClauseKind<'tcx>), - - /// Trait must be object-safe. - ObjectSafe(DefId), - - /// No direct syntax. May be thought of as `where T: FnFoo<...>` - /// for some generic args `...` and `T` being a closure type. - /// Satisfied (or refuted) once we know the closure's kind. - ClosureKind(DefId, GenericArgsRef<'tcx>, ClosureKind), - - /// `T1 <: T2` - /// - /// This obligation is created most often when we have two - /// unresolved type variables and hence don't have enough - /// information to process the subtyping obligation yet. - Subtype(SubtypePredicate<'tcx>), - - /// `T1` coerced to `T2` - /// - /// Like a subtyping obligation, this is created most often - /// when we have two unresolved type variables and hence - /// don't have enough information to process the coercion - /// obligation yet. At the moment, we actually process coercions - /// very much like subtyping and don't handle the full coercion - /// logic. - Coerce(CoercePredicate<'tcx>), - - /// Constants must be equal. The first component is the const that is expected. - ConstEquate(Const<'tcx>, Const<'tcx>), - - /// A marker predicate that is always ambiguous. - /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous. - Ambiguous, - - /// Separate from `ClauseKind::Projection` which is used for normalization in new solver. - /// This predicate requires two terms to be equal to eachother. - /// - /// Only used for new solver - AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection), -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[derive(HashStable, Debug, TyEncodable, TyDecodable)] -pub enum AliasRelationDirection { - Equate, - Subtype, -} - -impl std::fmt::Display for AliasRelationDirection { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - AliasRelationDirection::Equate => write!(f, "=="), - AliasRelationDirection::Subtype => write!(f, "<:"), - } - } -} - /// The crate outlives map is computed during typeck and contains the /// outlives of every item in the local crate. You should not use it /// directly, because to do so will make your pass dependent on the diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index f6fabe691c6a7..4152a7970982a 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -80,8 +80,66 @@ impl PartialEq for ClauseKind { } } +impl PartialOrd for ClauseKind +where + I::Ty: PartialOrd, + I::Const: PartialOrd, + I::GenericArg: PartialOrd, + I::TraitPredicate: PartialOrd, + I::ProjectionPredicate: PartialOrd, + I::TypeOutlivesPredicate: PartialOrd, + I::RegionOutlivesPredicate: PartialOrd, +{ + fn partial_cmp(&self, other: &Self) -> Option { + match (self, other) { + (Self::Trait(l0), Self::Trait(r0)) => l0.partial_cmp(r0), + (Self::RegionOutlives(l0), Self::RegionOutlives(r0)) => l0.partial_cmp(r0), + (Self::TypeOutlives(l0), Self::TypeOutlives(r0)) => l0.partial_cmp(r0), + (Self::Projection(l0), Self::Projection(r0)) => l0.partial_cmp(r0), + (Self::ConstArgHasType(l0, l1), Self::ConstArgHasType(r0, r1)) => { + let o = l0.partial_cmp(r0)?; + if !o.is_eq() { + return Some(o); + } + l1.partial_cmp(r1) + } + (Self::WellFormed(l0), Self::WellFormed(r0)) => l0.partial_cmp(r0), + (Self::ConstEvaluatable(l0), Self::ConstEvaluatable(r0)) => l0.partial_cmp(r0), + _ => Some(clause_kind_discriminant(self).cmp(&clause_kind_discriminant(other))), + } + } +} + +impl Ord for ClauseKind +where + I::Ty: Ord, + I::Const: Ord, + I::GenericArg: Ord, + I::TraitPredicate: Ord, + I::ProjectionPredicate: Ord, + I::TypeOutlivesPredicate: Ord, + I::RegionOutlivesPredicate: Ord, +{ + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + match (self, other) { + (Self::Trait(l0), Self::Trait(r0)) => l0.cmp(r0), + (Self::RegionOutlives(l0), Self::RegionOutlives(r0)) => l0.cmp(r0), + (Self::TypeOutlives(l0), Self::TypeOutlives(r0)) => l0.cmp(r0), + (Self::Projection(l0), Self::Projection(r0)) => l0.cmp(r0), + (Self::ConstArgHasType(l0, l1), Self::ConstArgHasType(r0, r1)) => { + l0.cmp(r0).then_with(|| l1.cmp(r1)) + } + (Self::WellFormed(l0), Self::WellFormed(r0)) => l0.cmp(r0), + (Self::ConstEvaluatable(l0), Self::ConstEvaluatable(r0)) => l0.cmp(r0), + _ => clause_kind_discriminant(self).cmp(&clause_kind_discriminant(other)), + } + } +} + impl Eq for ClauseKind {} +// FIXME: Ord for ClauseKind + fn clause_kind_discriminant(value: &ClauseKind) -> usize { match value { ClauseKind::Trait(_) => 0, @@ -345,6 +403,88 @@ impl PartialEq for PredicateKind { impl Eq for PredicateKind {} +impl Ord for PredicateKind +where + I::DefId: Ord, + I::Const: Ord, + I::GenericArgs: Ord, + I::Term: Ord, + I::CoercePredicate: Ord, + I::SubtypePredicate: Ord, + I::ClosureKind: Ord, + ClauseKind: Ord, +{ + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + match (self, other) { + (Self::Clause(l0), Self::Clause(r0)) => l0.cmp(r0), + (Self::ObjectSafe(l0), Self::ObjectSafe(r0)) => l0.cmp(r0), + (Self::ClosureKind(l0, l1, l2), Self::ClosureKind(r0, r1, r2)) => { + l0.cmp(r0).then_with(|| l1.cmp(r1).then_with(|| l2.cmp(r2))) + } + (Self::Subtype(l0), Self::Subtype(r0)) => l0.cmp(r0), + (Self::Coerce(l0), Self::Coerce(r0)) => l0.cmp(r0), + (Self::ConstEquate(l0, l1), Self::ConstEquate(r0, r1)) => { + l0.cmp(r0).then_with(|| l1.cmp(r1)) + } + (Self::AliasRelate(l0, l1, l2), Self::AliasRelate(r0, r1, r2)) => { + l0.cmp(r0).then_with(|| l1.cmp(r1).then_with(|| l2.cmp(r2))) + } + _ => predicate_kind_discriminant(self).cmp(&predicate_kind_discriminant(other)), + } + } +} + +impl PartialOrd for PredicateKind +where + I::DefId: PartialOrd, + I::Const: PartialOrd, + I::GenericArgs: PartialOrd, + I::Term: PartialOrd, + I::CoercePredicate: PartialOrd, + I::SubtypePredicate: PartialOrd, + I::ClosureKind: PartialOrd, + ClauseKind: PartialOrd, +{ + fn partial_cmp(&self, other: &Self) -> Option { + match (self, other) { + (Self::Clause(l0), Self::Clause(r0)) => l0.partial_cmp(r0), + (Self::ObjectSafe(l0), Self::ObjectSafe(r0)) => l0.partial_cmp(r0), + (Self::ClosureKind(l0, l1, l2), Self::ClosureKind(r0, r1, r2)) => { + let o = l0.partial_cmp(r0)?; + if !o.is_eq() { + return Some(o); + } + let o = l1.partial_cmp(r1)?; + if !o.is_eq() { + return Some(o); + } + l2.partial_cmp(r2) + } + (Self::Subtype(l0), Self::Subtype(r0)) => l0.partial_cmp(r0), + (Self::Coerce(l0), Self::Coerce(r0)) => l0.partial_cmp(r0), + (Self::ConstEquate(l0, l1), Self::ConstEquate(r0, r1)) => { + let o = l0.partial_cmp(r0)?; + if !o.is_eq() { + return Some(o); + } + l1.partial_cmp(r1) + } + (Self::AliasRelate(l0, l1, l2), Self::AliasRelate(r0, r1, r2)) => { + let o = l0.partial_cmp(r0)?; + if !o.is_eq() { + return Some(o); + } + let o = l1.partial_cmp(r1)?; + if !o.is_eq() { + return Some(o); + } + l2.partial_cmp(r2) + } + _ => Some(predicate_kind_discriminant(self).cmp(&predicate_kind_discriminant(other))), + } + } +} + fn predicate_kind_discriminant(value: &PredicateKind) -> usize { match value { PredicateKind::Clause(_) => 0,