diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index ce4c21ff8d86e..af779152ed675 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -239,26 +239,21 @@ fn compare_method_predicate_entailment<'tcx>( let hybrid_preds = hybrid_preds.into_iter().map(Unnormalized::skip_norm_wip); let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id); let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds)); - // FIXME(-Zhigher-ranked-assumptions): The `hybrid_preds` + // NOTE(-Zhigher-ranked-assumptions): The `hybrid_preds` // should be well-formed. However, using them may result in // region errors as we currently don't track placeholder // assumptions. // - // To avoid being backwards incompatible with the old solver, - // we also eagerly normalize the where-bounds in the new solver - // here while ignoring region constraints. This means we can then - // use where-bounds whose normalization results in placeholder - // errors further down without getting any errors. + // We eagerly normalize the where-clauses here while ignoring + // region constraints. This means we can then use where-bounds + // whose normalization results in placeholder errors further + // down without getting any errors. // - // It should be sound to do so as the only region errors here + // This should be sound to do so as the only region errors here // should be due to missing implied bounds. // // cc trait-system-refactor-initiative/issues/166. - let param_env = if tcx.next_trait_solver_globally() { - traits::deeply_normalize_param_env_ignoring_regions(tcx, param_env, normalize_cause) - } else { - traits::normalize_param_env_or_error(tcx, param_env, normalize_cause) - }; + let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); debug!(caller_bounds=?param_env.caller_bounds()); let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis()); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index c4a1b56320ff1..ef9efcc0d3f13 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -298,7 +298,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { self.param_env.caller_bounds().iter().filter_map(|predicate| { match predicate.kind().skip_binder() { ty::ClauseKind::Trait(data) if data.self_ty().is_param(index) => { - Some((predicate, span)) + Some((ty::set_aliases_to_non_rigid(tcx, predicate).skip_norm_wip(), span)) } _ => None, } diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index 6166560a671a0..b84c6d0aed42d 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -90,7 +90,8 @@ pub(super) fn can_match_erased_ty<'tcx>( // deal with rigid aliases, making sure we do so correctly // everywhere is effort, so we're just using `No` everywhere // for now. This should change soon. - let outlives_ty = ty::set_aliases_to_non_rigid(tcx, outlives_ty).skip_normalization(); + let (outlives_ty, erased_ty) = + ty::set_aliases_to_non_rigid(tcx, (outlives_ty, erased_ty)).skip_normalization(); if outlives_ty == erased_ty { // pointless micro-optimization true diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 9a9801aa3f3f7..3c07a32471bdb 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -258,6 +258,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { let erased_p_ty = self.tcx.erase_and_anonymize_regions( ty::set_aliases_to_non_rigid(self.tcx, p_ty).skip_norm_wip(), ); + let erased_ty = ty::set_aliases_to_non_rigid(self.tcx, erased_ty).skip_norm_wip(); (erased_p_ty == erased_ty).then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r))) })); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 569a1d5786095..ac7f73b532cf0 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2692,6 +2692,10 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.opts.unstable_opts.disable_fast_paths } + pub fn disable_param_env_hack(self) -> bool { + self.sess.opts.unstable_opts.disable_param_env_hack + } + pub fn renormalize_rigid_aliases(self) -> bool { self.sess.opts.unstable_opts.renormalize_rigid_aliases } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index efc8a70f4feb2..804824ecc7bce 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2347,6 +2347,8 @@ options! { "disable various performance optimizations in trait solving"), disable_incr_comp_backend_caching: bool = (false, parse_bool, [TRACKED], "disable caching of compiled objects by the codegen backend during incremental compilation"), + disable_param_env_hack: bool = (false, parse_bool, [TRACKED], + "do not try to mark param env as rigid for the next solver"), dual_proc_macros: bool = (false, parse_bool, [TRACKED], "load proc macros for both target and host, but only link to the target (default: no)"), dump_dep_graph: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index a98d06351f258..9a8345475dfd6 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -30,7 +30,6 @@ use rustc_errors::ErrorGuaranteed; pub use rustc_infer::traits::*; use rustc_macros::TypeVisitable; use rustc_middle::query::Providers; -use rustc_middle::span_bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ self, Clause, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder, @@ -250,6 +249,25 @@ fn pred_known_to_hold_modulo_regions<'tcx>( } } +fn set_projection_term_to_non_rigid<'tcx>( + tcx: TyCtxt<'tcx>, + predicates: impl IntoIterator>, +) -> impl Iterator> { + predicates.into_iter().map(move |clause| { + if let ty::ClauseKind::Projection(projection_pred) = clause.kind().skip_binder() { + clause + .kind() + .rebind(ty::ProjectionPredicate { + projection_term: projection_pred.projection_term, + term: ty::set_aliases_to_non_rigid(tcx, projection_pred.term).skip_norm_wip(), + }) + .upcast(tcx) + } else { + clause + } + }) +} + #[instrument(level = "debug", skip(tcx, elaborated_env))] fn do_normalize_predicates<'tcx>( tcx: TyCtxt<'tcx>, @@ -257,12 +275,6 @@ fn do_normalize_predicates<'tcx>( elaborated_env: ty::ParamEnv<'tcx>, predicates: Vec>, ) -> Result>, ErrorGuaranteed> { - // Even if we move back to eager normalization elsewhere, - // param env normalization remains lazy in the next solver. - if tcx.next_trait_solver_globally() { - return Ok(predicates); - } - // FIXME. We should really... do something with these region // obligations. But this call just continues the older // behavior (i.e., doesn't cause any new bugs), and it would @@ -279,10 +291,36 @@ fn do_normalize_predicates<'tcx>( let span = cause.span; let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); + // FIXME: The `elaborated_env` is not really rigid. We do this to be + // consistent with the old solver. It fixes several issues with + // lazy norm of param env but unfix others. + let elaborated_env = if tcx.next_trait_solver_globally() && !tcx.disable_param_env_hack() { + // FIXME: combine them into one if the perf is bad. + let elaborated_env = ty::set_aliases_to_rigid(tcx, elaborated_env); + let elaborated_env = set_projection_term_to_non_rigid(tcx, elaborated_env.caller_bounds()); + ty::ParamEnv::new(tcx.mk_clauses_from_iter(elaborated_env)) + } else { + elaborated_env + }; let predicates = ocx.normalize(&cause, elaborated_env, Unnormalized::new_wip(predicates)); - // FIXME: opaque types in param env might be in defining scope but we're - // using non body analysis for here. So the rigidness marker is wrong. - let predicates = ty::set_aliases_to_non_rigid(tcx, predicates).skip_norm_wip(); + let predicates = if tcx.next_trait_solver_globally() { + if !tcx.disable_param_env_hack() { + let predicates: Vec<_> = set_projection_term_to_non_rigid(tcx, predicates).collect(); + // FIXME(type_alias_impl_trait): opaque types in param env might be + // in defining scope but we're using non body analysis here. + // So the rigidness marker is wrong. + ty::set_opaques_to_non_rigid(tcx, predicates).skip_norm_wip() + } else { + // Param env is used in different typing modes but itself + // is normalized in `non_body_analysis`. + // That not only makes the rigidness of opaques types wrong, + // other aliases can be indirectly affected as well. + // So we conservatively set everything to be non-rigid. + ty::set_aliases_to_non_rigid(tcx, predicates).skip_norm_wip() + } + } else { + predicates + }; let errors = ocx.evaluate_obligations_error_on_ambiguity(); if !errors.is_empty() { @@ -294,17 +332,20 @@ fn do_normalize_predicates<'tcx>( // We can use the `elaborated_env` here; the region code only // cares about declarations like `'a: 'b`. + // // FIXME: It's very weird that we ignore region obligations but apparently // still need to use `resolve_regions` as we need the resolved regions in // the normalized predicates. - let errors = infcx.resolve_regions(cause.body_id, elaborated_env, []); - if !errors.is_empty() { - tcx.dcx().span_delayed_bug( - span, - format!("failed region resolution while normalizing {elaborated_env:?}: {errors:?}"), - ); - } - + // + // FIXME(-Zhigher-ranked-assumptions): We're ignoring region errors for now. + // There're placeholder constraints `leaking` out. This is a hack to work around + // the fact that we don't support placeholder assumptions right now and is necessary + // for `compare_method_predicate_entailment`. We should remove this once we + // have proper support for implied bounds on binders. + // + // This is required by trait-system-refactor-initiative#166. The new solver encounters + // this more frequently as we entirely ignore outlives predicates with the old solver. + let _errors = infcx.resolve_regions(cause.body_id, elaborated_env, []); match infcx.fully_resolve(predicates) { Ok(predicates) => Ok(predicates), Err(fixup_err) => { @@ -481,69 +522,6 @@ pub fn normalize_param_env_or_error<'tcx>( ty::ParamEnv::new(tcx.mk_clauses(&predicates)) } -/// Deeply normalize the param env using the next solver ignoring -/// region errors. -/// -/// FIXME(-Zhigher-ranked-assumptions): this is a hack to work around -/// the fact that we don't support placeholder assumptions right now -/// and is necessary for `compare_method_predicate_entailment`, see the -/// use of this function for more info. We should remove this once we -/// have proper support for implied bounds on binders. -#[instrument(level = "debug", skip(tcx))] -pub fn deeply_normalize_param_env_ignoring_regions<'tcx>( - tcx: TyCtxt<'tcx>, - unnormalized_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, -) -> ty::ParamEnv<'tcx> { - let predicates: Vec<_> = - util::elaborate(tcx, unnormalized_env.caller_bounds().into_iter()).collect(); - - debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates); - - let elaborated_env = ty::ParamEnv::new(tcx.mk_clauses(&predicates)); - if !elaborated_env.has_aliases() { - return elaborated_env; - } - - let span = cause.span; - let infcx = tcx - .infer_ctxt() - .with_next_trait_solver(true) - .ignoring_regions() - .build(TypingMode::non_body_analysis()); - let predicates = match crate::solve::deeply_normalize::<_, FulfillmentError<'tcx>>( - infcx.at(&cause, elaborated_env), - Unnormalized::new_wip(predicates), - ) { - Ok(predicates) => predicates, - Err(errors) => { - infcx.err_ctxt().report_fulfillment_errors(errors); - // An unnormalized env is better than nothing. - debug!("normalize_param_env_or_error: errored resolving predicates"); - return elaborated_env; - } - }; - - debug!("do_normalize_predicates: normalized predicates = {:?}", predicates); - // FIXME(-Zhigher-ranked-assumptions): We're ignoring region errors for now. - // There're placeholder constraints `leaking` out. - // See the fixme in the enclosing function's docs for more. - let _errors = infcx.resolve_regions(cause.body_id, elaborated_env, []); - - let predicates = match infcx.fully_resolve(predicates) { - Ok(predicates) => predicates, - Err(fixup_err) => { - span_bug!( - span, - "inference variables in normalized parameter environment: {}", - fixup_err - ) - } - }; - debug!("normalize_param_env_or_error: final predicates={:?}", predicates); - ty::ParamEnv::new(tcx.mk_clauses(&predicates)) -} - #[derive(Debug)] pub enum EvaluateConstErr { /// The constant being evaluated was either a generic parameter or inference variable, *or*, diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 8b1401c0609f9..d16c77954b9bc 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -559,16 +559,58 @@ pub fn set_aliases_to_non_rigid(cx: I, value: T) -> ty::Unnormal where T: TypeFoldable, { - if !value.has_rigid_aliases() { - return ty::Unnormalized::new(value); + let folded = set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::AllToNonRigid); + ty::Unnormalized::new(folded) +} + +pub fn set_opaques_to_non_rigid(cx: I, value: T) -> ty::Unnormalized +where + T: TypeFoldable, +{ + let folded = set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::OpaqueToNonRigid); + ty::Unnormalized::new(folded) +} + +// FIXME: take `Unnormalized` as input? +pub fn set_aliases_to_rigid(cx: I, value: T) -> T +where + T: TypeFoldable, +{ + set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::AllToRigid) +} + +fn set_aliases_rigidness_with_mode(cx: I, value: T, mode: RigidnessFoldMode) -> T +where + T: TypeFoldable, +{ + if !mode.needs_change(&value) { + return value; } - let mut folder = RigidnessFolder { cx }; - ty::Unnormalized::new(value.fold_with(&mut folder)) + let mut folder = RigidnessFolder { cx, mode }; + value.fold_with(&mut folder) +} + +enum RigidnessFoldMode { + AllToNonRigid, + AllToRigid, + OpaqueToNonRigid, +} + +impl RigidnessFoldMode { + fn needs_change>(&self, v: &T) -> bool { + match self { + RigidnessFoldMode::AllToRigid => v.has_non_rigid_aliases(), + RigidnessFoldMode::AllToNonRigid => v.has_rigid_aliases(), + RigidnessFoldMode::OpaqueToNonRigid => v.has_rigid_aliases() && v.has_opaque_types(), + } + } } +// Set aliases to be rigid or non-rigid according to the mode. struct RigidnessFolder { cx: I, + mode: RigidnessFoldMode, } impl TypeFolder for RigidnessFolder { @@ -578,42 +620,66 @@ impl TypeFolder for RigidnessFolder { } fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { - if t.has_rigid_aliases() { t.super_fold_with(self) } else { t } + if self.mode.needs_change(&t) { t.super_fold_with(self) } else { t } } fn fold_ty(&mut self, t: I::Ty) -> I::Ty { - if !t.has_rigid_aliases() { + if !self.mode.needs_change(&t) { return t; } match t.kind() { - ty::Alias(ty::IsRigid::Yes, alias_ty) => { + ty::Alias(is_rigid, alias_ty) => { let alias_ty = alias_ty.fold_with(self); - I::Ty::new_alias(self.cx(), ty::IsRigid::No, alias_ty) + match self.mode { + RigidnessFoldMode::AllToRigid => { + I::Ty::new_alias(self.cx(), ty::IsRigid::Yes, alias_ty) + } + RigidnessFoldMode::AllToNonRigid => { + I::Ty::new_alias(self.cx(), ty::IsRigid::No, alias_ty) + } + RigidnessFoldMode::OpaqueToNonRigid => { + if let ty::AliasTyKind::Opaque { .. } = alias_ty.kind { + I::Ty::new_alias(self.cx(), ty::IsRigid::No, alias_ty) + } else { + I::Ty::new_alias(self.cx(), is_rigid, alias_ty) + } + } + } } _ => t.super_fold_with(self), } } fn fold_const(&mut self, c: I::Const) -> I::Const { - if !c.has_rigid_aliases() { + if !self.mode.needs_change(&c) { return c; } match c.kind() { - ty::ConstKind::Alias(ty::IsRigid::Yes, alias_const) => { + ty::ConstKind::Alias(is_rigid, alias_const) => { let alias_const = alias_const.fold_with(self); - I::Const::new_alias(self.cx, ty::IsRigid::No, alias_const) + match self.mode { + RigidnessFoldMode::AllToRigid => { + I::Const::new_alias(self.cx, ty::IsRigid::Yes, alias_const) + } + RigidnessFoldMode::AllToNonRigid => { + I::Const::new_alias(self.cx(), ty::IsRigid::No, alias_const) + } + RigidnessFoldMode::OpaqueToNonRigid => { + I::Const::new_alias(self.cx(), is_rigid, alias_const) + } + } } _ => c.super_fold_with(self), } } fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { - if p.has_rigid_aliases() { p.super_fold_with(self) } else { p } + if self.mode.needs_change(&p) { p.super_fold_with(self) } else { p } } fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses { - if c.has_rigid_aliases() { c.super_fold_with(self) } else { c } + if self.mode.needs_change(&c) { c.super_fold_with(self) } else { c } } } diff --git a/tests/crashes/136661.rs b/tests/crashes/136661.rs deleted file mode 100644 index 76161a566f4c7..0000000000000 --- a/tests/crashes/136661.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ known-bug: #136661 - -#![allow(unused)] - -trait Supertrait {} - -trait Other { - fn method(&self) {} -} - -impl WithAssoc for &'static () { - type As = (); -} - -trait WithAssoc { - type As; -} - -trait Trait: Supertrait { - fn method(&self) {} -} - -fn hrtb Trait<&'a ()>>() {} - -pub fn main() {} diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr index 2351b18fdfc90..f136f5ffc82b4 100644 --- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:36:5 + --> $DIR/false-positive-predicate-entailment-error.rs:41:5 | LL | / fn autobatch(self) -> impl Trait ... | @@ -8,7 +8,7 @@ LL | | F: Callback, | |_______________________________________^ the trait `MyFn` is not implemented for `F` | note: required for `F` to implement `Callback` - --> $DIR/false-positive-predicate-entailment-error.rs:14:21 + --> $DIR/false-positive-predicate-entailment-error.rs:19:21 | LL | impl> Callback for F { | ------- ^^^^^^^^^^^ ^ @@ -20,7 +20,7 @@ LL | F: Callback + MyFn, | +++++++++++ error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:36:5 + --> $DIR/false-positive-predicate-entailment-error.rs:41:5 | LL | / fn autobatch(self) -> impl Trait ... | @@ -29,7 +29,7 @@ LL | | F: Callback, | |_______________________________________^ the trait `MyFn` is not implemented for `F` | note: required for `F` to implement `Callback` - --> $DIR/false-positive-predicate-entailment-error.rs:14:21 + --> $DIR/false-positive-predicate-entailment-error.rs:19:21 | LL | impl> Callback for F { | ------- ^^^^^^^^^^^ ^ @@ -42,20 +42,20 @@ LL | F: Callback + MyFn, | +++++++++++ error[E0277]: the trait bound `F: Callback` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:42:12 + --> $DIR/false-positive-predicate-entailment-error.rs:48:12 | LL | F: Callback, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn` is not implemented for `F` | note: required for `F` to implement `Callback` - --> $DIR/false-positive-predicate-entailment-error.rs:14:21 + --> $DIR/false-positive-predicate-entailment-error.rs:19:21 | LL | impl> Callback for F { | ------- ^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here note: the requirement `F: Callback` appears on the `impl`'s method `autobatch` but not on the corresponding trait's method - --> $DIR/false-positive-predicate-entailment-error.rs:25:8 + --> $DIR/false-positive-predicate-entailment-error.rs:30:8 | LL | trait ChannelSender { | ------------- in this trait @@ -68,13 +68,13 @@ LL | F: Callback + MyFn, | +++++++++++ error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:36:30 + --> $DIR/false-positive-predicate-entailment-error.rs:41:30 | LL | fn autobatch(self) -> impl Trait | ^^^^^^^^^^ the trait `MyFn` is not implemented for `F` | note: required for `F` to implement `Callback` - --> $DIR/false-positive-predicate-entailment-error.rs:14:21 + --> $DIR/false-positive-predicate-entailment-error.rs:19:21 | LL | impl> Callback for F { | ------- ^^^^^^^^^^^ ^ @@ -82,13 +82,13 @@ LL | impl> Callback for F { | unsatisfied trait bound introduced here error[E0277]: the trait bound `F: Callback` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:27:12 + --> $DIR/false-positive-predicate-entailment-error.rs:32:12 | LL | F: Callback; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn` is not implemented for `F` | note: required for `F` to implement `Callback` - --> $DIR/false-positive-predicate-entailment-error.rs:14:21 + --> $DIR/false-positive-predicate-entailment-error.rs:19:21 | LL | impl> Callback for F { | ------- ^^^^^^^^^^^ ^ @@ -96,7 +96,7 @@ LL | impl> Callback for F { | unsatisfied trait bound introduced here error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:36:5 + --> $DIR/false-positive-predicate-entailment-error.rs:41:5 | LL | / fn autobatch(self) -> impl Trait ... | @@ -105,7 +105,7 @@ LL | | F: Callback, | |_______________________________________^ the trait `MyFn` is not implemented for `F` | note: required for `F` to implement `Callback` - --> $DIR/false-positive-predicate-entailment-error.rs:14:21 + --> $DIR/false-positive-predicate-entailment-error.rs:19:21 | LL | impl> Callback for F { | ------- ^^^^^^^^^^^ ^ @@ -118,13 +118,13 @@ LL | F: Callback + MyFn, | +++++++++++ error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:42:12 + --> $DIR/false-positive-predicate-entailment-error.rs:48:12 | LL | F: Callback, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn` is not implemented for `F` | note: required by a bound in `Callback` - --> $DIR/false-positive-predicate-entailment-error.rs:10:20 + --> $DIR/false-positive-predicate-entailment-error.rs:15:20 | LL | trait Callback: MyFn { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Callback` diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.next.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.next.stderr new file mode 100644 index 0000000000000..90569d9aecd4b --- /dev/null +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.next.stderr @@ -0,0 +1,107 @@ +error[E0277]: the trait bound `F: MyFn` is not satisfied + --> $DIR/false-positive-predicate-entailment-error.rs:41:5 + | +LL | / fn autobatch(self) -> impl Trait +... | +LL | | where +LL | | F: Callback, + | |_______________________________________^ the trait `MyFn` is not implemented for `F` + | +note: required for `F` to implement `Callback` + --> $DIR/false-positive-predicate-entailment-error.rs:19:21 + | +LL | impl> Callback for F { + | ------- ^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +help: consider further restricting type parameter `F` with trait `MyFn` + | +LL | F: Callback + MyFn, + | +++++++++++ + +error[E0277]: the trait bound `F: MyFn` is not satisfied + --> $DIR/false-positive-predicate-entailment-error.rs:41:5 + | +LL | / fn autobatch(self) -> impl Trait +... | +LL | | where +LL | | F: Callback, + | |_______________________________________^ the trait `MyFn` is not implemented for `F` + | +note: required for `F` to implement `Callback` + --> $DIR/false-positive-predicate-entailment-error.rs:19:21 + | +LL | impl> Callback for F { + | ------- ^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider further restricting type parameter `F` with trait `MyFn` + | +LL | F: Callback + MyFn, + | +++++++++++ + +error[E0277]: the trait bound `F: MyFn` is not satisfied + --> $DIR/false-positive-predicate-entailment-error.rs:41:5 + | +LL | / fn autobatch(self) -> impl Trait +... | +LL | | where +LL | | F: Callback, + | |_______________________________________^ the trait `MyFn` is not implemented for `F` + | +note: required for `F` to implement `Callback` + --> $DIR/false-positive-predicate-entailment-error.rs:19:21 + | +LL | impl> Callback for F { + | ------- ^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider further restricting type parameter `F` with trait `MyFn` + | +LL | F: Callback + MyFn, + | +++++++++++ + +error[E0277]: the trait bound `F: MyFn` is not satisfied + | +note: required for `F` to implement `Callback` + --> $DIR/false-positive-predicate-entailment-error.rs:19:21 + | +LL | impl> Callback for F { + | ------- ^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0277]: the trait bound `F: MyFn` is not satisfied + --> $DIR/false-positive-predicate-entailment-error.rs:41:30 + | +LL | fn autobatch(self) -> impl Trait + | ^^^^^^^^^^ the trait `MyFn` is not implemented for `F` + | +note: required for `F` to implement `Callback` + --> $DIR/false-positive-predicate-entailment-error.rs:19:21 + | +LL | impl> Callback for F { + | ------- ^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0277]: the trait bound `F: MyFn` is not satisfied + --> $DIR/false-positive-predicate-entailment-error.rs:41:30 + | +LL | fn autobatch(self) -> impl Trait + | ^^^^^^^^^^ the trait `MyFn` is not implemented for `F` + | +note: required for `F` to implement `Callback` + --> $DIR/false-positive-predicate-entailment-error.rs:19:21 + | +LL | impl> Callback for F { + | ------- ^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs index cbe6c32b8901c..044765233f56d 100644 --- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs @@ -1,7 +1,12 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[next] check-pass + +// This was fixed by lazy norm of param env with the next solver. +// But it regressed again as we switched back to be consistent with +// the old solver. See #158643. + +//[next]~^^^^^^^^ ERROR: the trait bound `F: MyFn` is not satisfied trait MyFn { type Output; @@ -34,10 +39,11 @@ impl ChannelSender for Sender { type CallbackArg = i32; fn autobatch(self) -> impl Trait - //[current]~^ ERROR the trait bound `F: MyFn` is not satisfied - //[current]~| ERROR the trait bound `F: MyFn` is not satisfied - //[current]~| ERROR the trait bound `F: MyFn` is not satisfied - //[current]~| ERROR the trait bound `F: MyFn` is not satisfied + //~^ ERROR the trait bound `F: MyFn` is not satisfied + //~| ERROR the trait bound `F: MyFn` is not satisfied + //~| ERROR the trait bound `F: MyFn` is not satisfied + //~| ERROR the trait bound `F: MyFn` is not satisfied + //[next]~| ERROR the trait bound `F: MyFn` is not satisfied where F: Callback, //[current]~^ ERROR the trait bound `F: MyFn` is not satisfied diff --git a/tests/ui/specialization/min_specialization/next-solver-region-resolution.rs b/tests/ui/specialization/min_specialization/next-solver-region-resolution.rs index 2bd8529df3991..16c0f80b1c8dd 100644 --- a/tests/ui/specialization/min_specialization/next-solver-region-resolution.rs +++ b/tests/ui/specialization/min_specialization/next-solver-region-resolution.rs @@ -16,7 +16,7 @@ where } impl<'a, T> Foo for &T -//~^ ERROR: conflicting implementations of trait `Foo` for type `&_` +//~^ ERROR: cycle detected when computing normalized predicates of `` where Self::Item: Baz, { diff --git a/tests/ui/specialization/min_specialization/next-solver-region-resolution.stderr b/tests/ui/specialization/min_specialization/next-solver-region-resolution.stderr index cae27b4b31097..4c2dc5e8e71fa 100644 --- a/tests/ui/specialization/min_specialization/next-solver-region-resolution.stderr +++ b/tests/ui/specialization/min_specialization/next-solver-region-resolution.stderr @@ -1,17 +1,22 @@ -error[E0119]: conflicting implementations of trait `Foo` for type `&_` +error[E0391]: cycle detected when computing normalized predicates of `` --> $DIR/next-solver-region-resolution.rs:18:1 | -LL | / impl<'a, T> Foo for &'a T -LL | | where -LL | | Self::Item: 'a, - | |___________________- first implementation here -... LL | / impl<'a, T> Foo for &T LL | | LL | | where LL | | Self::Item: Baz, - | |____________________^ conflicting implementation for `&_` + | |____________________^ + | + = note: ...which immediately requires computing normalized predicates of `` again +note: cycle used when computing whether impls specialize one another + --> $DIR/next-solver-region-resolution.rs:12:1 + | +LL | / impl<'a, T> Foo for &'a T +LL | | where +LL | | Self::Item: 'a, + | |___________________^ + = note: for more information, see and error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr index 1e450571ed9da..147b248c33da8 100644 --- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr @@ -18,8 +18,9 @@ LL | fn accept0(_: Container<{ T::make() }>) {} = note: ...which requires building an abstract representation for `accept0::{constant#0}`... = note: ...which requires building THIR for `accept0::{constant#0}`... = note: ...which requires type-checking `accept0::{constant#0}`... + = note: ...which requires computing normalized predicates of `accept0::{constant#0}`... = note: ...which again requires evaluating type-level constant, completing the cycle - = note: cycle used when checking that `accept0` is well-formed + = note: cycle used when computing normalized predicates of `accept0` = note: for more information, see and error[E0391]: cycle detected when checking if `accept1::{constant#0}` is a trivial const @@ -32,6 +33,7 @@ LL | const fn accept1(_: Container<{ T::make() }>) {} = note: ...which requires building an abstract representation for `accept1::{constant#0}`... = note: ...which requires building THIR for `accept1::{constant#0}`... = note: ...which requires type-checking `accept1::{constant#0}`... + = note: ...which requires computing normalized predicates of `accept1::{constant#0}`... = note: ...which requires evaluating type-level constant... = note: ...which requires const-evaluating + checking `accept1::{constant#0}`... = note: ...which again requires checking if `accept1::{constant#0}` is a trivial const, completing the cycle diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs index 432b13d161afb..7c3985f30cae9 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs @@ -21,6 +21,7 @@ trait Foo { impl Foo for () { type Item = String where String: Copy; //~^ ERROR overflow evaluating the requirement `String: Copy` + //~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275] } fn main() { diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr index b20534f5dc584..d82c5016eeaca 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr @@ -1,3 +1,9 @@ +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` + --> $DIR/alias-bound-unsound.rs:22:5 + | +LL | type Item = String where String: Copy; + | ^^^^^^^^^ + error[E0275]: overflow evaluating the requirement `String: Copy` --> $DIR/alias-bound-unsound.rs:22:38 | @@ -13,17 +19,17 @@ LL | type Item: Copy | ^^^^ this trait's associated type doesn't have the requirement `String: Copy` error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == String` - --> $DIR/alias-bound-unsound.rs:28:22 + --> $DIR/alias-bound-unsound.rs:29:22 | LL | let _ = identity(<() as Foo>::copy_me(&x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` - --> $DIR/alias-bound-unsound.rs:28:43 + --> $DIR/alias-bound-unsound.rs:29:43 | LL | let _ = identity(<() as Foo>::copy_me(&x)); | ^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs index ffbbecaf89570..83e300b077428 100644 --- a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs @@ -38,6 +38,7 @@ fn impls_bound() { // - normalize `>::Assoc` // - via blanket impl, requires where-clause `Foo: Bound` -> cycle fn generic() +//~^ ERROR the trait bound `Foo: Bound` is not satisfied where >::Assoc: Bound, //~^ ERROR the trait bound `Foo: Bound` is not satisfied diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr index f679b94a92377..e18265190278a 100644 --- a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr @@ -1,5 +1,32 @@ error[E0277]: the trait bound `Foo: Bound` is not satisfied - --> $DIR/normalizes-to-is-not-productive.rs:42:31 + --> $DIR/normalizes-to-is-not-productive.rs:40:1 + | +LL | / fn generic() +LL | | +LL | | where +LL | | >::Assoc: Bound, + | |____________________________________^ unsatisfied trait bound + | +help: the trait `Bound` is not implemented for `Foo` + --> $DIR/normalizes-to-is-not-productive.rs:18:1 + | +LL | struct Foo; + | ^^^^^^^^^^ +help: the trait `Bound` is implemented for `u32` + --> $DIR/normalizes-to-is-not-productive.rs:11:1 + | +LL | impl Bound for u32 { + | ^^^^^^^^^^^^^^^^^^ +note: required for `Foo` to implement `Trait` + --> $DIR/normalizes-to-is-not-productive.rs:23:19 + | +LL | impl Trait for T { + | ----- ^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0277]: the trait bound `Foo: Bound` is not satisfied + --> $DIR/normalizes-to-is-not-productive.rs:43:31 | LL | >::Assoc: Bound, | ^^^^^ unsatisfied trait bound @@ -30,7 +57,7 @@ LL | | } | |_^ required by this bound in `Bound` error[E0277]: the trait bound `Foo: Bound` is not satisfied - --> $DIR/normalizes-to-is-not-productive.rs:47:19 + --> $DIR/normalizes-to-is-not-productive.rs:48:19 | LL | impls_bound::(); | ^^^ unsatisfied trait bound @@ -51,6 +78,6 @@ note: required by a bound in `impls_bound` LL | fn impls_bound() { | ^^^^^ required by this bound in `impls_bound` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs index 914773c82196a..4d088073c3ba6 100644 --- a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs +++ b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs @@ -14,7 +14,7 @@ fn foo() where T: for<'a> Proj<'a, Assoc = for<'b> fn(>::Assoc)>, (): Trait<>::Assoc> - //~^ ERROR: overflow evaluating the requirement `(): Trait<>::Assoc>` + //~^ ERROR: the trait bound `(): Trait fn(>::Assoc))>` is not satisfied { } diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr index e2ee83cfadbef..1408890184a90 100644 --- a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr +++ b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr @@ -1,11 +1,14 @@ -error[E0275]: overflow evaluating the requirement `(): Trait<>::Assoc>` +error[E0277]: the trait bound `(): Trait fn(>::Assoc))>` is not satisfied --> $DIR/find-param-recursion-issue-152716.rs:16:9 | LL | (): Trait<>::Assoc> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait fn(>::Assoc))>` is not implemented for `()` | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`find_param_recursion_issue_152716`) +help: consider extending the `where` clause, but there might be an alternative better way to express this requirement + | +LL | (): Trait<>::Assoc>, (): Trait fn(>::Assoc))> + | +++++++++++++++++++++++++++++++++++++++++++++++++++ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-1.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-1.rs index 6f5fdd561f4e4..ecac4f9dfbbc5 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-1.rs +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-1.rs @@ -1,6 +1,9 @@ -//@ check-pass //@ compile-flags: -Znext-solver -// Issue 108933 + +// Regression test for #108933. +// This was fixed by lazy norm of param env with the next solver. +// But it regressed again as we switched back to be consistent with +// the old solver. See #158643. trait Add { type Sum; @@ -24,6 +27,7 @@ where } fn g() +//~^ ERROR: the trait bound `T: Trait<()>` is not satisfied where T: Trait, >::Output: Sized, diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-1.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-1.stderr new file mode 100644 index 0000000000000..05377b998d2d7 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-1.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `T: Trait<()>` is not satisfied + --> $DIR/normalize-param-env-1.rs:29:1 + | +LL | / fn g() +LL | | +LL | | where +LL | | T: Trait, +LL | | >::Output: Sized, + | |____________________________________^ the trait `Trait<()>` is not implemented for `T` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr index d3effe2eb0389..f5ff41fc17aae 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr @@ -1,78 +1,37 @@ -error[E0275]: overflow evaluating the requirement `<() as A>::Assoc == _` - --> $DIR/normalize-param-env-2.rs:22:5 +error[E0276]: impl has stricter requirements than trait + --> $DIR/normalize-param-env-2.rs:24:22 | LL | / fn f() LL | | where LL | | Self::Assoc: A, - | |__________________________^ - -error[E0275]: overflow evaluating the requirement `<() as A>::Assoc == _` - --> $DIR/normalize-param-env-2.rs:24:22 - | -LL | Self::Assoc: A, - | ^^^^ + | |__________________________- definition of `f` from trait +... +LL | Self::Assoc: A, + | ^^^^ impl has extra requirement `<() as A>::Assoc: A` -error[E0283]: type annotations needed +error[E0277]: the trait bound `<() as A>::Assoc: A` is not satisfied --> $DIR/normalize-param-env-2.rs:24:22 | LL | Self::Assoc: A, - | ^^^^ cannot infer type + | ^^^^ the trait `A` is not implemented for `<() as A>::Assoc` | -note: multiple `impl`s or `where` clauses satisfying `_: A` found +help: the trait `A` is implemented for `()` --> $DIR/normalize-param-env-2.rs:19:1 | LL | impl A for () { | ^^^^^^^^^^^^^^^^^^^ -... -LL | Self::Assoc: A, - | ^^^^ -note: the requirement `_: A` appears on the `impl`'s associated function `f` but not on the corresponding trait's associated function - --> $DIR/normalize-param-env-2.rs:12:8 - | -LL | trait A { - | - in this trait -... -LL | fn f() - | ^ this trait's associated function doesn't have the requirement `_: A` -error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: A` - --> $DIR/normalize-param-env-2.rs:24:22 - | -LL | Self::Assoc: A, - | ^^^^ - -error[E0275]: overflow evaluating whether `<() as A>::Assoc` is well-formed - --> $DIR/normalize-param-env-2.rs:24:22 - | -LL | Self::Assoc: A, - | ^^^^ - -error[E0275]: overflow evaluating the requirement `(): A` - --> $DIR/normalize-param-env-2.rs:27:10 +error[E0277]: the trait bound `<() as A>::Assoc: A` is not satisfied + --> $DIR/normalize-param-env-2.rs:27:18 | LL | <() as A>::f(); - | ^^ - -error[E0275]: overflow evaluating the requirement `<() as A>::Assoc == _` - --> $DIR/normalize-param-env-2.rs:27:9 + | ^ the trait `A` is not implemented for `<() as A>::Assoc` | -LL | <() as A>::f(); - | ^^^^^^^^^^^^^^^^^ - -error[E0283]: type annotations needed - --> $DIR/normalize-param-env-2.rs:27:9 - | -LL | <() as A>::f(); - | ^^^^^^^^^^^^^^^^^ cannot infer type - | -note: multiple `impl`s or `where` clauses satisfying `_: A` found +help: the trait `A` is implemented for `()` --> $DIR/normalize-param-env-2.rs:19:1 | LL | impl A for () { | ^^^^^^^^^^^^^^^^^^^ -... -LL | Self::Assoc: A, - | ^^^^ note: required by a bound in `A::f` --> $DIR/normalize-param-env-2.rs:14:22 | @@ -82,7 +41,7 @@ LL | where LL | Self::Assoc: A, | ^^^^ required by this bound in `A::f` -error: aborting due to 8 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0275, E0283. -For more information about an error, try `rustc --explain E0275`. +Some errors have detailed explanations: E0276, E0277. +For more information about an error, try `rustc --explain E0276`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-3.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-3.rs index 9d895df5d3ee4..5bfd25318f527 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-3.rs +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-3.rs @@ -1,6 +1,9 @@ -//@ check-pass //@ compile-flags: -Znext-solver -// Issue 100177 + +// Regression test for #100177. +// This was fixed by lazy norm of param env with the next solver. +// But it regressed again as we switched back to be consistent with +// the old solver. See #158643. trait GenericTrait {} @@ -20,6 +23,8 @@ impl Sender for T { type Msg = (); fn send() + //~^ ERROR: the trait bound `C: Channel<()>` is not satisfied + //~| ERROR: the trait bound `C: Channel<()>` is not satisfied where C: Channel, { diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-3.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-3.stderr new file mode 100644 index 0000000000000..3c70f1221aa0e --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-3.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `C: Channel<()>` is not satisfied + --> $DIR/normalize-param-env-3.rs:25:5 + | +LL | / fn send() +LL | | +LL | | +LL | | where +LL | | C: Channel, + | |______________________________^ the trait `Channel<()>` is not implemented for `C` + +error[E0277]: the trait bound `C: Channel<()>` is not satisfied + --> $DIR/normalize-param-env-3.rs:25:5 + | +LL | / fn send() +LL | | +LL | | +LL | | where +LL | | C: Channel, + | |______________________________^ the trait `Channel<()>` is not implemented for `C` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr deleted file mode 100644 index 47d38365e970e..0000000000000 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0275]: overflow evaluating the requirement `::Assoc: Trait` - --> $DIR/normalize-param-env-4.rs:19:26 - | -LL | ::Assoc: Trait, - | ^^^^^ - -error[E0275]: overflow evaluating whether `::Assoc` is well-formed - --> $DIR/normalize-param-env-4.rs:19:26 - | -LL | ::Assoc: Trait, - | ^^^^^ - -error[E0275]: overflow evaluating the requirement `T: Trait` - --> $DIR/normalize-param-env-4.rs:32:19 - | -LL | impls_trait::(); - | ^ - | -note: required by a bound in `impls_trait` - --> $DIR/normalize-param-env-4.rs:15:19 - | -LL | fn impls_trait() {} - | ^^^^^ required by this bound in `impls_trait` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.rs index ed7f6899bdee6..9a4191bcc8b78 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.rs +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.rs @@ -1,8 +1,10 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[next] known-bug: #92505 -//@[current] check-pass +//@ check-pass + +// Issue #92505. +// Now that we eager norm param env in the next solver, it compiles. trait Trait { type Assoc; diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-5.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-5.rs new file mode 100644 index 0000000000000..3b9dd9e230940 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-5.rs @@ -0,0 +1,39 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#246 +// Fixed by eager norm and marking param env as rigid. + +struct MarkedStruct; +pub trait MarkerTrait {} +impl MarkerTrait for MarkedStruct {} + +struct ChainStruct; +trait ChainTrait {} +impl ChainTrait for ChainStruct where MarkedStruct: MarkerTrait {} + +pub struct FooStruct; +pub trait FooTrait { + type Output; +} +pub struct FooOut; +impl FooTrait for FooStruct +where + ChainStruct: ChainTrait, +{ + type Output = FooOut; +} +type FooOutAlias = ::Output; + +pub trait Trait { + type Output; +} + +pub fn foo() +where + FooOut: Trait, + >::Output: MarkerTrait, +{ +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-6.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-6.rs new file mode 100644 index 0000000000000..5756b76d7131c --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-6.rs @@ -0,0 +1,70 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#246 +// Fixed by eager norm and marking param env as rigid. + +#![feature(rustc_attrs)] +#![rustc_no_implicit_bounds] +// makes it work: +// #![recursion_limit = "512"] + +pub trait Trait { + type K; +} + +// two different types +pub struct T1; +pub struct T2; + +// a type that's easy to make really large +pub struct Growing(T); +// for which proving that it implements foo grows with that size +pub trait Foo { + type Output; +} +impl Foo for Growing { + type Output = ::Output; +} +impl Foo for T2 { + type Output = T1; +} +// a simple way to do this proof +pub type Eval = ::Output; + +// a trivial trait bound for one of the types +pub trait Trivial {} +impl Trivial for T1 {} + +// and one for which one of the possible impls diverges +pub trait Diverges {} +impl Diverges for I {} +impl Diverges for I +where + R: Trivial, // move this bound down + Growing: Diverges, +{ +} + +// Our large type +type LargeToEval = Growing>>>; + +impl Trait for K +where + (): Diverges, + T1: Trivial, + Eval: Trivial, +{ + type K = K; +} + +fn foo() +where + Eval: Trivial, + Eval<::K>: Trivial, +{ +} + +fn main() { + foo() +} diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-7.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-7.rs new file mode 100644 index 0000000000000..8ba7b389f23c6 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-7.rs @@ -0,0 +1,655 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#246 +// There're some smaller intermediate minimizations in the issue comments +// but they may not catch the same problem as in the full version. +// +// Fixed by eager norm and marking param env as rigid. See #158643. + +use std::ops::{BitAnd, BitOr, BitXor, Neg, Not, Shl, Shr}; +pub struct B0; + +impl Clone for B0 { + fn clone(&self) -> B0 { + loop {} + } +} + +impl Copy for B0 {} + +impl Default for B0 { + fn default() -> B0 { + loop {} + } +} + +pub struct B1; + +impl Clone for B1 { + fn clone(&self) -> B1 { + loop {} + } +} + +impl Copy for B1 {} + +impl Default for B1 { + fn default() -> B1 { + loop {} + } +} + +impl Bit for B0 { + const U8: u8 = 0; + const BOOL: bool = false; +} +impl Bit for B1 { + const U8: u8 = 1; + const BOOL: bool = true; +} + +pub type U0 = UTerm; +pub type U1 = UInt; + +pub type U2 = UInt, B0>; + +pub trait NonZero {} + +pub trait Ord {} +pub trait Bit: Copy + Default + 'static { + const U8: u8; + const BOOL: bool; +} +pub trait Unsigned: Copy + Default + 'static { +} + +pub type Shleft = >::Output; + +pub type Sum = >::Output; +pub type Diff = >::Output; +pub type Prod = >::Output; +pub type Quot = >::Output; + +pub type Gcf = >::Output; +pub type Add1 = >::Output; +pub type Sub1 = >::Output; + +pub type Compare = >::Output; +pub type Length = ::Output; + +pub type Minimum = >::Output; +pub type Maximum = >::Output; + +pub trait Trim { + type Output; +} +pub type TrimOut = ::Output; +pub trait TrimTrailingZeros { + type Output; +} + +pub trait Invert { + type Output; +} + +pub trait PrivateInvert { + type Output; +} +pub type PrivateInvertOut = >::Output; +pub struct InvertedUTerm; +pub struct InvertedUInt { + msb: IU, + lsb: B, +} + +pub trait PrivateSub { + type Output; +} +pub type PrivateSubOut = >::Output; + +pub trait InvertedUnsigned {} +impl InvertedUnsigned for InvertedUTerm {} +impl InvertedUnsigned for InvertedUInt {} + +impl Invert for UInt +where + U: PrivateInvert>, +{ + type Output = PrivateInvertOut>; +} +impl PrivateInvert for UTerm { + type Output = IU; +} +impl PrivateInvert for UInt +where + U: PrivateInvert>, +{ + type Output = PrivateInvertOut>; +} +impl Invert for InvertedUTerm { + type Output = UTerm; +} +impl Invert for InvertedUInt +where + IU: PrivateInvert>, +{ + type Output = >>::Output; +} +impl PrivateInvert for InvertedUTerm { + type Output = U; +} +impl PrivateInvert for InvertedUInt +where + IU: PrivateInvert>, +{ + type Output = >>::Output; +} +impl TrimTrailingZeros for InvertedUTerm { + type Output = InvertedUTerm; +} +impl TrimTrailingZeros for InvertedUInt { + type Output = Self; +} +impl TrimTrailingZeros for InvertedUInt +where + IU: TrimTrailingZeros, +{ + type Output = ::Output; +} +impl Trim for U +where + U: Invert, + ::Output: TrimTrailingZeros, + <::Output as TrimTrailingZeros>::Output: Invert, +{ + type Output = <<::Output as TrimTrailingZeros>::Output as Invert>::Output; +} +pub trait PrivateCmp { + type Output; +} +pub type PrivateCmpOut = >::Output; +pub trait PrivateSetBit { + type Output; +} +pub type PrivateSetBitOut = >::Output; +pub trait PrivateDiv { + type Quotient; + type Remainder; +} +pub type PrivateDivQuot = <() as PrivateDiv>::Quotient; +pub type PrivateDivRem = <() as PrivateDiv>::Remainder; +pub trait PrivateDivIf { + type Quotient; + type Remainder; +} +pub type PrivateDivIfQuot = + <() as PrivateDivIf>::Quotient; +pub type PrivateDivIfRem = + <() as PrivateDivIf>::Remainder; + +pub trait PrivateMin { + type Output; +} +pub type PrivateMinOut = >::Output; +pub trait PrivateMax { + type Output; +} +pub type PrivateMaxOut = >::Output; + +pub trait Cmp { + type Output; +} + +pub trait Len { + type Output; +} + +pub trait Min { + type Output; +} +pub trait Max { + type Output; +} + +pub trait Gcd { + type Output; +} + +pub struct UTerm; + +impl Clone for UTerm { + fn clone(&self) -> UTerm { + loop {} + } +} + +impl Copy for UTerm {} + +impl Default for UTerm { + fn default() -> UTerm { + loop {} + } +} + +impl Unsigned for UTerm { +} +pub struct UInt { + pub(crate) msb: U, + pub(crate) lsb: B, +} + +impl Clone for UInt { + fn clone(&self) -> UInt { + loop {} + } +} + +impl Copy for UInt {} + +impl Default for UInt { + fn default() -> UInt { + loop {} + } +} + +impl Unsigned for UInt { +} +impl NonZero for UInt {} + +impl Len for UTerm { + type Output = U0; +} +impl Len for UInt +where + U: Len, + Length: Add, + Add1>: Unsigned, +{ + type Output = Add1>; +} + +impl Add for UTerm { + type Output = UInt; + fn add(self, _: B1) -> Self::Output { + loop {} + } +} + +impl Add for UInt +where + U: Add, + Add1: Unsigned, +{ + type Output = UInt, B0>; + fn add(self, _: B1) -> Self::Output { + loop {} + } +} +impl Add for UTerm { + type Output = U; + fn add(self, rhs: U) -> Self::Output { + loop {} + } +} + +impl Add> for UInt +where + Ul: Add, +{ + type Output = UInt, B1>; + fn add(self, rhs: UInt) -> Self::Output { + loop {} + } +} + +impl Sub for UInt { + type Output = UTerm; + fn sub(self, _: B1) -> Self::Output { + loop {} + } +} +impl Sub for UInt +where + U: Sub, + Sub1: Unsigned, +{ + type Output = UInt, B1>; + fn sub(self, _: B1) -> Self::Output { + loop {} + } +} + +impl Sub for UInt +where + UInt: PrivateSub, + PrivateSubOut, Ur>: Trim, +{ + type Output = TrimOut, Ur>>; + fn sub(self, rhs: Ur) -> Self::Output { + loop {} + } +} +impl PrivateSub for U { + type Output = U; +} + +impl PrivateSub> for UInt +where + Ul: PrivateSub, +{ + type Output = UInt, B0>; +} + +impl Shl for UInt { + type Output = UInt; + fn shl(self, _: UTerm) -> Self::Output { + loop {} + } +} + +impl Shl> for UInt +where + UInt: Sub, + UInt, B0>: Shl>>, +{ + type Output = Shleft, B0>, Sub1>>; + fn shl(self, rhs: UInt) -> Self::Output { + loop {} + } +} + +impl Mul for UTerm { + type Output = UTerm; + fn mul(self, _: U) -> Self::Output { + loop {} + } +} +impl Mul> for UInt +where + Ul: Mul>, +{ + type Output = UInt>, B0>; + fn mul(self, rhs: UInt) -> Self::Output { + loop {} + } +} +impl Mul> for UInt +where + Ul: Mul>, + UInt>, B0>: Add>, +{ + type Output = Sum>, B0>, UInt>; + fn mul(self, rhs: UInt) -> Self::Output { + loop {} + } +} + +impl Cmp> for UTerm { + type Output = Less; +} +impl Cmp> for UInt +where + Ul: PrivateCmp, +{ + type Output = PrivateCmpOut; +} +impl Cmp> for UInt +where + Ul: PrivateCmp, +{ + type Output = PrivateCmpOut; +} + +impl Cmp> for UInt +where + Ul: PrivateCmp, +{ + type Output = PrivateCmpOut; +} + +impl PrivateCmp, SoFar> for UInt +where + Ul: Unsigned, + Ur: Unsigned, + SoFar: Ord, + Ul: PrivateCmp, +{ + type Output = PrivateCmpOut; +} + +impl PrivateCmp, SoFar> for UTerm { + type Output = Less; +} + +impl PrivateCmp for UTerm { + type Output = SoFar; +} + +type Even = UInt; +type Odd = UInt; + +impl Gcd for U0 { + type Output = Y; +} + +impl Gcd> for Even +where + Xp: Gcd>, + Even: NonZero, +{ + type Output = Gcf>; +} +impl Gcd> for Odd +where + Odd: Max> + Min>, + Odd: Max>, + Maximum, Odd>: Sub, Odd>>, + Diff, Odd>, Minimum, Odd>>: Gcd, Odd>>, +{ + type Output = + Gcf, Odd>, Minimum, Odd>>, Minimum, Odd>>; +} + +pub trait GetBit { + type Output; +} + +pub type GetBitOut = >::Output; +impl GetBit for UInt { + type Output = Bn; +} +impl GetBit> for UInt +where + UInt: Copy + Sub, + Un: GetBit>>, +{ + type Output = GetBitOut>>; +} + +pub trait SetBit { + type Output; +} +pub type SetBitOut = >::Output; + +impl SetBit for N +where + N: PrivateSetBit, + PrivateSetBitOut: Trim, +{ + type Output = TrimOut>; +} + +impl PrivateSetBit for UTerm +where + U1: Shl, +{ + type Output = Shleft; +} + +impl Div> for UInt +where + UInt: Len, + Length>: Sub, + (): PrivateDiv, UInt, U0, U0, Sub1>>>, +{ + type Output = PrivateDivQuot, UInt, U0, U0, Sub1>>>; + fn div(self, rhs: UInt) -> Self::Output { + loop {} + } +} + +impl PrivateDiv for () +where + N: GetBit, + UInt>: Trim, + TrimOut>>: Cmp, + (): PrivateDivIf< + N, + D, + Q, + TrimOut>>, + I, + Compare>>, D>, + >, +{ + type Quotient = PrivateDivIfQuot< + N, + D, + Q, + TrimOut>>, + I, + Compare>>, D>, + >; + type Remainder = PrivateDivIfRem< + N, + D, + Q, + TrimOut>>, + I, + Compare>>, D>, + >; +} +impl PrivateDiv, I> for () +where + N: GetBit, + UInt, GetBitOut>: Cmp, + (): PrivateDivIf< + N, + D, + Q, + UInt, GetBitOut>, + I, + Compare, GetBitOut>, D>, + >, +{ + type Quotient = PrivateDivIfQuot< + N, + D, + Q, + UInt, GetBitOut>, + I, + Compare, GetBitOut>, D>, + >; + type Remainder = PrivateDivIfRem< + N, + D, + Q, + UInt, GetBitOut>, + I, + Compare, GetBitOut>, D>, + >; +} + +impl PrivateDivIf, Less> for () +where + UInt: Sub, + (): PrivateDiv>>, +{ + type Quotient = PrivateDivQuot>>; + type Remainder = PrivateDivRem>>; +} +impl PrivateDivIf, Equal> for () +where + UInt: Copy + Sub, + Q: SetBit, B1>, + (): PrivateDiv, B1>, U0, Sub1>>, +{ + type Quotient = PrivateDivQuot, B1>, U0, Sub1>>; + type Remainder = PrivateDivRem, B1>, U0, Sub1>>; +} + +impl PrivateDivIf for () { + type Quotient = Q; + type Remainder = R; +} +impl PrivateDivIf for () +where + Q: SetBit, +{ + type Quotient = SetBitOut; + type Remainder = U0; +} + +impl PrivateMin for UInt { + type Output = UInt; +} + +impl Min for UInt +where + U: Unsigned, + B: Bit, + Ur: Unsigned, + UInt: Cmp + PrivateMin, Ur>>, +{ + type Output = PrivateMinOut, Ur, Compare, Ur>>; +} + +impl PrivateMax for UInt { + type Output = UInt; +} + +impl Max for UInt +where + U: Unsigned, + B: Bit, + Ur: Unsigned, + UInt: Cmp + PrivateMax, Ur>>, +{ + type Output = PrivateMaxOut, Ur, Compare, Ur>>; +} + +pub struct Greater; + +pub struct Less; + +pub struct Equal; + +impl Ord for Greater {} + +impl Ord for Equal {} + +use std::ops::{Add, Div, Mul, Rem, Sub}; + +pub trait EncodingSize { + type EncodedPolynomialSize; +} +impl EncodingSize for D +where + D: Mul + Gcd, + Prod: Div>, + Quot, Gcf>: Div, +{ + type EncodedPolynomialSize = D; +} + +pub fn foo

() +where + U2: Mul

, + Prod: Add + Div

, + ::EncodedPolynomialSize: Mul

, + Sum, U0>: Sub, Output = U0>, +{ +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize/param_env-region-constraints-ambiguity.rs b/tests/ui/traits/next-solver/normalize/param_env-region-constraints-ambiguity.rs new file mode 100644 index 0000000000000..08a7148ca5e88 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/param_env-region-constraints-ambiguity.rs @@ -0,0 +1,101 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#265. Different where-clauses +// normalizing to the same bound caused ambiguity errors if we lazily normalized +// where-clauses when using them to prove a goal. +// +// We avoid these errors by eagerly normalizing the `param_env`. + +mod one { + trait Trait { + type Assoc<'a> + where + Self: 'a; + } + + trait Bound<'a> {} + fn impls_bound<'a, T: Bound<'a>>() {} + fn foo<'a, T: 'a>() + where + T: Trait = T> + Bound<'a>, + T::Assoc<'a>: Bound<'a>, + { + impls_bound::<'_, T>(); + } +} + +mod two { + trait Trait { + type Assoc<'a> + where + Self: 'a; + } + + trait Bound {} + fn impls_bound() {} + fn foo<'a, T: 'a>() + where + T: Trait = T> + Bound, + T::Assoc<'a>: Bound, + { + impls_bound::(); + } +} + +// Minimization of tokio-par-util. +mod three { + trait Trait1 { + type Assoc1; + } + + trait Trait2 { + type Assoc2; + } + + struct Indir(T); + impl Trait2 for Indir + where + T: Trait1, + T::Assoc1: Trait2 + 'static, + { + type Assoc2 = ::Assoc2; + } + + struct WrapperTwo(T, U); + + impl Trait1 for WrapperTwo + where + T: Trait1, + T::Assoc1: Trait2 + 'static, + // additional region constraint in this candidate so they + // can't be merged. + U: Trait1 as Trait2>::Assoc2>, + U: Trait1::Assoc2>, + { + type Assoc1 = i32; + } +} + +// Minimization of `qazer` +mod four { + trait Value { + type SelfType<'a> + where + Self: 'a; + } + + trait Repository {} + struct RedbRepo(From, Into); + + impl Repository for RedbRepo + where + for<'a> From: Value = From> + Clone + 'static, + for<'a> ::SelfType<'a>: Clone, + { + } +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs index c61fbef05b224..8dc27c0da605a 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs @@ -13,7 +13,7 @@ fn needs_bar() {} fn test::Assoc2> + Foo2::Assoc1>>() { needs_bar::(); - //~^ ERROR: the trait bound `::Assoc2: Bar` is not satisfied + //~^ ERROR: the trait bound `::Assoc1: Bar` is not satisfied } fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr index c4be47e3520da..6f5111a6193ca 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `::Assoc2: Bar` is not satisfied +error[E0277]: the trait bound `::Assoc1: Bar` is not satisfied --> $DIR/recursive-self-normalization-2.rs:15:17 | LL | needs_bar::(); - | ^^^^^^^^^ the trait `Bar` is not implemented for `::Assoc2` + | ^^^^^^^^^ the trait `Bar` is not implemented for `::Assoc1` | note: required by a bound in `needs_bar` --> $DIR/recursive-self-normalization-2.rs:12:17 @@ -11,7 +11,7 @@ LL | fn needs_bar() {} | ^^^ required by this bound in `needs_bar` help: consider further restricting the associated type | -LL | fn test::Assoc2> + Foo2::Assoc1>>() where ::Assoc2: Bar { +LL | fn test::Assoc2> + Foo2::Assoc1>>() where ::Assoc1: Bar { | ++++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-1.rs b/tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-1.rs new file mode 100644 index 0000000000000..7fcb164d3a95d --- /dev/null +++ b/tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-1.rs @@ -0,0 +1,41 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// In `fn hrtb` normalizing the elaborated where-clause +// `T: for<'a> Supertrait<<&'a () as WithAssoc>::As>` results in +// a region error as `&'a ()` is not equal to `&'static ()`. +// +// This happens even though the where-clauses themselves are well-formed +// as we never have to prove `&'a (): WithAssoc` as `'a` is a bound variable. +// +// I don't think this can cause unsoundness and has already been accepted in the +// old solver as we didn't register TypeOutlives constraints if `ignoring_regions` +// is set. The new solver always registers outlives constraints, so this then +// caused an error there. We need to ignore these region errors with the new solver +// due to trait-system-refactor-initiative#166. + +#![allow(unused)] + +trait Supertrait {} + +trait Other { + fn method(&self) {} +} + +impl WithAssoc for T { + type As = T; +} + +trait WithAssoc { + type As; +} + +trait Trait: Supertrait { + fn method(&self) {} +} + +fn hrtb Trait<&'a ()>>() {} + +pub fn main() {} diff --git a/tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-2.rs b/tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-2.rs new file mode 100644 index 0000000000000..9339518aae1a0 --- /dev/null +++ b/tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-2.rs @@ -0,0 +1,39 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// In `fn hrtb` normalizing the elaborated where-clause +// `T: for<'a> Supertrait<<&'a () as WithAssoc>::As>` results in +// a region error as `&'a ()` is not `'static`. +// +// This happens even though the where-clauses themselves are well-formed +// as we never have to prove `&'a (): WithAssoc` as `'a` is a bound variable. +// +// Unlike `normalize-param-env-missing-implied-bound-1.rs` this snippet caused +// an ICE with the old trait solver, as we did register region constraints from +// relating types. This ICE was tracked in #136661. + +#![allow(unused)] + +trait Supertrait {} + +trait Other { + fn method(&self) {} +} + +impl WithAssoc for &'static () { + type As = (); +} + +trait WithAssoc { + type As; +} + +trait Trait: Supertrait { + fn method(&self) {} +} + +fn hrtb Trait<&'a ()>>() {} + +pub fn main() {} diff --git a/tests/ui/typeck/issue-116864.current.stderr b/tests/ui/typeck/issue-116864.current.stderr new file mode 100644 index 0000000000000..b3fbf6b0e570f --- /dev/null +++ b/tests/ui/typeck/issue-116864.current.stderr @@ -0,0 +1,108 @@ +error[E0277]: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + --> $DIR/issue-116864.rs:28:1 + | +LL | / async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) +... | +LL | | where +LL | | BAZ: Baz, + | |__________________________^ expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + | + = note: expected a closure with signature `for<'any> fn(&'any i32)` + found a closure with signature `fn(&::Param)` +note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `for<'any> FnMutFut<&'any i32, ()>` + --> $DIR/issue-116864.rs:20:20 + | +LL | impl FnMutFut for F + | ^^^^^^^^^^^^^^ ^ +LL | where +LL | F: FnMut(P) -> FUT, + | --------------- unsatisfied trait bound introduced here + +error[E0277]: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + --> $DIR/issue-116864.rs:28:81 + | +LL | async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) + | ^ expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + | + = note: expected a closure with signature `for<'any> fn(&'any i32)` + found a closure with signature `fn(&::Param)` +note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `for<'any> FnMutFut<&'any i32, ()>` + --> $DIR/issue-116864.rs:20:20 + | +LL | impl FnMutFut for F + | ^^^^^^^^^^^^^^ ^ +LL | where +LL | F: FnMut(P) -> FUT, + | --------------- unsatisfied trait bound introduced here +note: required by a bound in `foo` + --> $DIR/issue-116864.rs:28:40 + | +LL | async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error[E0277]: expected an `FnMut(&i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + --> $DIR/issue-116864.rs:36:5 + | +LL | cb(&1i32).await; + | ^^^^^^^^^ expected an `FnMut(&i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + | + = note: expected a closure with signature `fn(&i32)` + found a closure with signature `fn(&::Param)` +note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `FnMutFut<&i32, ()>` + --> $DIR/issue-116864.rs:20:20 + | +LL | impl FnMutFut for F + | ^^^^^^^^^^^^^^ ^ +LL | where +LL | F: FnMut(P) -> FUT, + | --------------- unsatisfied trait bound introduced here + +error[E0308]: mismatched types + --> $DIR/issue-116864.rs:36:8 + | +LL | cb(&1i32).await; + | -- ^^^^^ expected `&::Param`, found `&i32` + | | + | arguments to this function are incorrect + | + = note: expected reference `&::Param` + found reference `&i32` + = help: consider constraining the associated type `::Param` to `i32` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: type parameter defined here + --> $DIR/issue-116864.rs:28:35 + | +LL | async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: call `Into::into` on this expression to convert `&i32` into `&::Param` + | +LL | cb((&1i32).into()).await; + | + ++++++++ + +error[E0277]: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + --> $DIR/issue-116864.rs:28:81 + | +LL | async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) + | ^ expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + | + = note: expected a closure with signature `for<'any> fn(&'any i32)` + found a closure with signature `fn(&::Param)` +note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `for<'any> FnMutFut<&'any i32, ()>` + --> $DIR/issue-116864.rs:20:20 + | +LL | impl FnMutFut for F + | ^^^^^^^^^^^^^^ ^ +LL | where +LL | F: FnMut(P) -> FUT, + | --------------- unsatisfied trait bound introduced here +note: required by a bound in `foo` + --> $DIR/issue-116864.rs:28:40 + | +LL | async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-116864.next.stderr b/tests/ui/typeck/issue-116864.next.stderr new file mode 100644 index 0000000000000..e7d951dcff260 --- /dev/null +++ b/tests/ui/typeck/issue-116864.next.stderr @@ -0,0 +1,23 @@ +error[E0277]: expected an `FnOnce(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + --> $DIR/issue-116864.rs:28:1 + | +LL | / async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) +... | +LL | | where +LL | | BAZ: Baz, + | |__________________________^ expected an `FnOnce(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + | + = note: expected a closure with signature `for<'any> fn(&'any i32)` + found a closure with signature `fn(&::Param)` +note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `for<'any> FnMutFut<&'any i32, ()>` + --> $DIR/issue-116864.rs:20:20 + | +LL | impl FnMutFut for F + | ^^^^^^^^^^^^^^ ^ +LL | where +LL | F: FnMut(P) -> FUT, + | --- unsatisfied trait bound introduced here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-116864.rs b/tests/ui/typeck/issue-116864.rs index 6cbe56b2f926a..568b56bfc44ee 100644 --- a/tests/ui/typeck/issue-116864.rs +++ b/tests/ui/typeck/issue-116864.rs @@ -1,7 +1,12 @@ -//@ compile-flags: -Znext-solver -//@ check-pass +//@ revisions: current next +//@[next] compile-flags: -Znext-solver //@ edition: 2021 +// This was fixed by lazy norm of param env with the next solver. +// But it regressed again as we switched back to be consistent with +// the old solver. See #158643. + + use std::future::Future; trait Baz { @@ -21,10 +26,16 @@ where } async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) +//[next]~^ ERROR: expected an `FnOnce(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` +//[current]~^^ ERROR: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` +//[current]~| ERROR: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` +//[current]~| ERROR: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` where BAZ: Baz, { cb(&1i32).await; + //[current]~^ ERROR: expected an `FnMut(&i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + //[current]~| ERROR: mismatched types } fn main() {