diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index b8a29a9a08f43..acc8ac0b62382 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -1,6 +1,7 @@ use rustc_ast as ast; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{NodeId, PatKind, attr, token}; +use rustc_errors::E0001; use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features}; use rustc_session::Session; use rustc_session::parse::{feature_err, feature_warn}; @@ -650,10 +651,13 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) { .map(|feat| feat.attr_sp) { #[allow(rustc::symbol_intern_string_literal)] - sess.dcx().emit_err(errors::IncompatibleFeatures { - spans: vec![gce_span], - f1: Symbol::intern("-Znext-solver=globally"), - f2: sym::generic_const_exprs, - }); + sess.dcx() + .create_fatal(errors::IncompatibleFeatures { + spans: vec![gce_span], + f1: Symbol::intern("-Znext-solver=globally"), + f2: sym::generic_const_exprs, + }) + .with_code(E0001) + .emit(); } } diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 82b7c578a1f25..c6f9086c2ffec 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -9,17 +9,18 @@ use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, InferResult}; -use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; +use rustc_infer::traits::{ObligationCause, ObligationCauseCode, PredicateObligations}; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::span_bug; +use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ - self, ClosureKind, GenericArgs, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, + self, ClosureKind, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; use rustc_span::def_id::LocalDefId; use rustc_span::{DUMMY_SP, Span}; use rustc_trait_selection::error_reporting::traits::ArgKind; -use rustc_trait_selection::traits; +use rustc_trait_selection::traits::{self, ObligationCtxt}; use tracing::{debug, instrument, trace}; use super::{CoroutineTypes, Expectation, FnCtxt, check_fn}; @@ -384,56 +385,83 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Make sure that we didn't infer a signature that mentions itself. // This can happen when we elaborate certain supertrait bounds that // mention projections containing the `Self` type. See #105401. - struct MentionsTy<'tcx> { - expected_ty: Ty<'tcx>, - } - impl<'tcx> TypeVisitor> for MentionsTy<'tcx> { - type Result = ControlFlow<()>; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { - if t == self.expected_ty { - ControlFlow::Break(()) - } else { - t.super_visit_with(self) - } - } - } - - // Don't infer a closure signature from a goal that names the closure type as this will - // (almost always) lead to occurs check errors later in type checking. + // + // Doing so will (almost always) lead to occurs check errors later in + // type checking. if self.next_trait_solver() && let Some(inferred_sig) = inferred_sig { - // In the new solver it is difficult to explicitly normalize the inferred signature as we - // would have to manually handle universes and rewriting bound vars and placeholders back - // and forth. - // - // Instead we take advantage of the fact that we relating an inference variable with an alias - // will only instantiate the variable if the alias is rigid(*not quite). Concretely we: - // - Create some new variable `?sig` - // - Equate `?sig` with the unnormalized signature, e.g. `fn( as Trait>::Assoc)` - // - Depending on whether ` as Trait>::Assoc` is rigid, ambiguous or normalizeable, - // we will either wind up with `?sig= as Trait>::Assoc/?y/ConcreteTy` respectively. - // - // *: In cases where there are ambiguous aliases in the signature that make use of bound vars - // they will wind up present in `?sig` even though they are non-rigid. + // If we've got `F: FnOnce(>::This)` we want to + // use this to infer the signature `FnOnce(u32)` for the closure. // - // This is a bit weird and means we may wind up discarding the goal due to it naming `expected_ty` - // even though the normalized form may not name `expected_ty`. However, this matches the existing - // behaviour of the old solver and would be technically a breaking change to fix. + // We handle self-referential aliases here by relying on generalization + // which replaces such aliases with inference variables. This is currently + // a bit too weak, see trait-system-refactor-initiative#191. + struct ReplaceTy<'tcx> { + tcx: TyCtxt<'tcx>, + expected_ty: Ty<'tcx>, + with_ty: Ty<'tcx>, + } + impl<'tcx> TypeFolder> for ReplaceTy<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + if t == self.expected_ty { + self.with_ty + } else { + t.super_fold_with(self) + } + } + } let generalized_fnptr_sig = self.next_ty_var(span); let inferred_fnptr_sig = Ty::new_fn_ptr(self.tcx, inferred_sig.sig); - self.demand_eqtype(span, inferred_fnptr_sig, generalized_fnptr_sig); - - let resolved_sig = self.resolve_vars_if_possible(generalized_fnptr_sig); - - if resolved_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() { - expected_sig = Some(ExpectedSig { - cause_span: inferred_sig.cause_span, - sig: resolved_sig.fn_sig(self.tcx), - }); + let inferred_fnptr_sig = inferred_fnptr_sig.fold_with(&mut ReplaceTy { + tcx: self.tcx, + expected_ty, + with_ty: generalized_fnptr_sig, + }); + let resolved_sig = self.commit_if_ok(|snapshot| { + let outer_universe = self.universe(); + let ocx = ObligationCtxt::new(self); + ocx.eq( + &ObligationCause::dummy(), + self.param_env, + generalized_fnptr_sig, + inferred_fnptr_sig, + )?; + if ocx.select_where_possible().is_empty() { + self.leak_check(outer_universe, Some(snapshot))?; + Ok(self.resolve_vars_if_possible(generalized_fnptr_sig)) + } else { + Err(TypeError::Mismatch) + } + }); + match resolved_sig { + Ok(resolved_sig) => { + expected_sig = Some(ExpectedSig { + cause_span: inferred_sig.cause_span, + sig: resolved_sig.fn_sig(self.tcx), + }) + } + Err(_) => {} } } else { + struct MentionsTy<'tcx> { + expected_ty: Ty<'tcx>, + } + impl<'tcx> TypeVisitor> for MentionsTy<'tcx> { + type Result = ControlFlow<()>; + + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { + if t == self.expected_ty { + ControlFlow::Break(()) + } else { + t.super_visit_with(self) + } + } + } if inferred_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() { expected_sig = inferred_sig; } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index 367e2b6b372ae..9a1d985586688 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -1,7 +1,6 @@ //! A utility module to inspect currently ambiguous obligations in the current context. use rustc_infer::traits::{self, ObligationCause, PredicateObligations}; -use rustc_middle::traits::solve::GoalSource; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_span::Span; use rustc_trait_selection::solve::Certainty; @@ -37,10 +36,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> bool { match predicate.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { - self.type_matches_expected_vid(expected_vid, data.self_ty()) + self.type_matches_expected_vid(data.self_ty(), expected_vid) } ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { - self.type_matches_expected_vid(expected_vid, data.projection_term.self_ty()) + self.type_matches_expected_vid(data.projection_term.self_ty(), expected_vid) } ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) | ty::PredicateKind::Subtype(..) @@ -60,7 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } #[instrument(level = "debug", skip(self), ret)] - fn type_matches_expected_vid(&self, expected_vid: ty::TyVid, ty: Ty<'tcx>) -> bool { + fn type_matches_expected_vid(&self, ty: Ty<'tcx>, expected_vid: ty::TyVid) -> bool { let ty = self.shallow_resolve(ty); debug!(?ty); @@ -76,7 +75,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, self_ty: ty::TyVid, ) -> PredicateObligations<'tcx> { - let obligations = self.fulfillment_cx.borrow().pending_obligations(); + let sub_root_var = self.sub_unification_table_root_var(self_ty); + let obligations = self + .fulfillment_cx + .borrow() + .pending_obligations_potentially_referencing_sub_root(sub_root_var); debug!(?obligations); let mut obligations_for_self_ty = PredicateObligations::new(); for obligation in obligations { @@ -125,23 +128,21 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'a, 'tcx> { return; } + // We don't care about any pending goals which don't actually + // use the self type. + if !inspect_goal + .orig_values() + .iter() + .filter_map(|arg| arg.as_type()) + .any(|ty| self.fcx.type_matches_expected_vid(ty, self.self_ty)) + { + debug!(goal = ?inspect_goal.goal(), "goal does not mention self type"); + return; + } + let tcx = self.fcx.tcx; let goal = inspect_goal.goal(); - if self.fcx.predicate_has_self_ty(goal.predicate, self.self_ty) - // We do not push the instantiated forms of goals as it would cause any - // aliases referencing bound vars to go from having escaping bound vars to - // being able to be normalized to an inference variable. - // - // This is mostly just a hack as arbitrary nested goals could still contain - // such aliases while having a different `GoalSource`. Closure signature inference - // however can't really handle *every* higher ranked `Fn` goal also being present - // in the form of `?c: Fn<(>::Assoc)`. - // - // This also just better matches the behaviour of the old solver where we do not - // encounter instantiated forms of goals, only nested goals that referred to bound - // vars from instantiated goals. - && !matches!(inspect_goal.source(), GoalSource::InstantiateHigherRanked) - { + if self.fcx.predicate_has_self_ty(goal.predicate, self.self_ty) { self.obligations_for_self_ty.push(traits::Obligation::new( tcx, self.root_cause.clone(), diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 9f5a85b692642..a615ac9d912dd 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -219,6 +219,12 @@ fn typeck_with_inspect<'tcx>( // the future. fcx.check_repeat_exprs(); + // We need to handle opaque types before emitting ambiguity errors as applying + // defining uses may guide type inference. + if fcx.next_trait_solver() { + fcx.try_handle_opaque_type_uses_next(); + } + fcx.type_inference_fallback(); // Even though coercion casts provide type hints, we check casts after fallback for diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs index 4c1fe69405e91..9b5f26cefff79 100644 --- a/compiler/rustc_hir_typeck/src/opaque_types.rs +++ b/compiler/rustc_hir_typeck/src/opaque_types.rs @@ -22,6 +22,29 @@ impl<'tcx> FnCtxt<'_, 'tcx> { /// inference variables. /// /// It then uses these defining uses to guide inference for all other uses. + /// + /// Unlike `handle_opaque_type_uses_next`, this does not report errors. + pub(super) fn try_handle_opaque_type_uses_next(&mut self) { + // We clone the opaques instead of stealing them here as they are still used for + // normalization in the next generation trait solver. + let mut opaque_types: Vec<_> = self.infcx.clone_opaque_types(); + for entry in &mut opaque_types { + *entry = self.resolve_vars_if_possible(*entry); + } + debug!(?opaque_types); + + self.compute_definition_site_hidden_types(&opaque_types, true); + self.apply_definition_site_hidden_types(&opaque_types); + } + + /// This takes all the opaque type uses during HIR typeck. It first computes + /// the concrete hidden type by iterating over all defining uses. + /// + /// A use during HIR typeck is defining if all non-lifetime arguments are + /// unique generic parameters and the hidden type does not reference any + /// inference variables. + /// + /// It then uses these defining uses to guide inference for all other uses. #[instrument(level = "debug", skip(self))] pub(super) fn handle_opaque_type_uses_next(&mut self) { // We clone the opaques instead of stealing them here as they are still used for @@ -35,7 +58,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { } debug!(?opaque_types); - self.compute_definition_site_hidden_types(&opaque_types); + self.compute_definition_site_hidden_types(&opaque_types, false); self.apply_definition_site_hidden_types(&opaque_types); } } @@ -74,6 +97,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { fn compute_definition_site_hidden_types( &mut self, opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)], + first_pass: bool, ) { let tcx = self.tcx; let TypingMode::Analysis { defining_opaque_types_and_generators } = self.typing_mode() @@ -94,12 +118,22 @@ impl<'tcx> FnCtxt<'_, 'tcx> { continue; } - usage_kind.merge(self.consider_opaque_type_use(opaque_type_key, hidden_type)); + usage_kind.merge(self.consider_opaque_type_use( + opaque_type_key, + hidden_type, + first_pass, + )); if let UsageKind::HasDefiningUse = usage_kind { break; } } + // If this the first pass (`try_handle_opaque_type_uses_next`), + // then do not report any errors. + if first_pass { + continue; + } + let guar = match usage_kind { UsageKind::None => { if let Some(guar) = self.tainted_by_errors() { @@ -152,6 +186,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { &mut self, opaque_type_key: OpaqueTypeKey<'tcx>, hidden_type: OpaqueHiddenType<'tcx>, + first_pass: bool, ) -> UsageKind<'tcx> { if let Err(err) = opaque_type_has_defining_use_args( &self, @@ -199,7 +234,13 @@ impl<'tcx> FnCtxt<'_, 'tcx> { .borrow_mut() .hidden_types .insert(opaque_type_key.def_id, hidden_type); - assert!(prev.is_none()); + + // We do want to insert opaque types the first pass, because we want to + // equate them. So, the second pass (where we report errors) will have + // a hidden type inserted. + if first_pass { + assert!(prev.is_none()); + } UsageKind::HasDefiningUse } @@ -209,10 +250,12 @@ impl<'tcx> FnCtxt<'_, 'tcx> { ) { let tcx = self.tcx; for &(key, hidden_type) in opaque_types { - let expected = *self.typeck_results.borrow_mut().hidden_types.get(&key.def_id).unwrap(); - - let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args); - self.demand_eqtype(hidden_type.span, expected, hidden_type.ty); + // On the first pass to this function, some opaque types may not + // have a hidden type assigned. + if let Some(expected) = self.typeck_results.borrow_mut().hidden_types.get(&key.def_id) { + let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args); + self.demand_eqtype(hidden_type.span, expected, hidden_type.ty); + } } } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index cc41957c110f7..206a9d2c4b4d5 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -6,8 +6,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::bug; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ - self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, TypingMode, + self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeVisitableExt, TypingMode, }; use rustc_span::Span; use tracing::{debug, instrument, warn}; @@ -290,45 +289,6 @@ impl<'tcx> InferCtxt<'tcx> { } } -/// Finds the max universe present -struct MaxUniverse { - max_universe: ty::UniverseIndex, -} - -impl MaxUniverse { - fn new() -> Self { - MaxUniverse { max_universe: ty::UniverseIndex::ROOT } - } - - fn max_universe(self) -> ty::UniverseIndex { - self.max_universe - } -} - -impl<'tcx> TypeVisitor> for MaxUniverse { - fn visit_ty(&mut self, t: Ty<'tcx>) { - if let ty::Placeholder(placeholder) = t.kind() { - self.max_universe = self.max_universe.max(placeholder.universe); - } - - t.super_visit_with(self) - } - - fn visit_const(&mut self, c: ty::Const<'tcx>) { - if let ty::ConstKind::Placeholder(placeholder) = c.kind() { - self.max_universe = self.max_universe.max(placeholder.universe); - } - - c.super_visit_with(self) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) { - if let ty::RePlaceholder(placeholder) = r.kind() { - self.max_universe = self.max_universe.max(placeholder.universe); - } - } -} - /// The "generalizer" is used when handling inference variables. /// /// The basic strategy for handling a constraint like `?A <: B` is to @@ -437,15 +397,8 @@ impl<'tcx> Generalizer<'_, 'tcx> { if is_nested_alias { return Err(e); } else { - let mut visitor = MaxUniverse::new(); - alias.visit_with(&mut visitor); - let infer_replacement_is_complete = - self.for_universe.can_name(visitor.max_universe()) - && !alias.has_escaping_bound_vars(); - if !infer_replacement_is_complete { - warn!("may incompletely handle alias type: {alias:?}"); - } - + // FIXME(trait-system-refactor-initiative#8): This is incomplete + // in case the alias has escaping bound vars. debug!("generalization failure in alias"); Ok(self.next_ty_var_for_alias()) } diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 4a252719694d5..216c16bd11e92 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -1,7 +1,7 @@ use std::fmt::Debug; use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, Ty, Upcast}; +use rustc_middle::ty::{self, Ty, TyVid, Upcast}; use super::{ObligationCause, PredicateObligation, PredicateObligations}; use crate::infer::InferCtxt; @@ -106,6 +106,15 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { fn has_pending_obligations(&self) -> bool; fn pending_obligations(&self) -> PredicateObligations<'tcx>; + // Returning all pending obligations which reference an inference + // variable with `_sub_root`. This assumes that no type inference + // progress has been made since the last `select_where_possible` call. + fn pending_obligations_potentially_referencing_sub_root( + &self, + _sub_root: TyVid, + ) -> PredicateObligations<'tcx> { + self.pending_obligations() + } /// Among all pending obligations, collect those are stalled on a inference variable which has /// changed since the last call to `select_where_possible`. Those obligations are marked as diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3c5c21a7a89c2..3e1f064310f43 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3480,7 +3480,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn next_trait_solver_globally(self) -> bool { - self.sess.opts.unstable_opts.next_solver.globally + self.sess.opts.unstable_opts.next_solver.globally && !self.features().generic_const_exprs() } pub fn next_trait_solver_in_coherence(self) -> bool { diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index f25003bbfe92a..5f75ebd79de1a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -201,7 +201,7 @@ where span: I::Span, stalled_on: Option>, ) -> Result, NoSolution> { - EvalCtxt::enter_root(self, self.cx().recursion_limit(), span, |ecx| { + EvalCtxt::enter_root(self, self.cx().recursion_limit() * 2, span, |ecx| { ecx.evaluate_goal(GoalSource::Misc, goal, stalled_on) }) } @@ -297,9 +297,6 @@ where // corecursive functions as explained in #136824, relating types never // introduces a constructor which could cause the recursion to be guarded. GoalSource::TypeRelating => PathKind::Inductive, - // Instantiating a higher ranked goal can never cause the recursion to be - // guarded and is therefore unproductive. - GoalSource::InstantiateHigherRanked => PathKind::Inductive, // These goal sources are likely unproductive and can be changed to // `PathKind::Inductive`. Keeping them as unknown until we're confident // about this and have an example where it is necessary. @@ -567,66 +564,56 @@ where pub(super) fn compute_goal(&mut self, goal: Goal) -> QueryResult { let Goal { param_env, predicate } = goal; let kind = predicate.kind(); - if let Some(kind) = kind.no_bound_vars() { - match kind { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => { - self.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r) - } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => { - self.compute_host_effect_goal(Goal { param_env, predicate }) - } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => { - self.compute_projection_goal(Goal { param_env, predicate }) - } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => { - self.compute_type_outlives_goal(Goal { param_env, predicate }) - } - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => { - self.compute_region_outlives_goal(Goal { param_env, predicate }) - } - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { - self.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) }) - } - ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => { - self.compute_unstable_feature_goal(param_env, symbol) - } - ty::PredicateKind::Subtype(predicate) => { - self.compute_subtype_goal(Goal { param_env, predicate }) - } - ty::PredicateKind::Coerce(predicate) => { - self.compute_coerce_goal(Goal { param_env, predicate }) - } - ty::PredicateKind::DynCompatible(trait_def_id) => { - self.compute_dyn_compatible_goal(trait_def_id) - } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { - self.compute_well_formed_goal(Goal { param_env, predicate: term }) - } - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => { - self.compute_const_evaluatable_goal(Goal { param_env, predicate: ct }) - } - ty::PredicateKind::ConstEquate(_, _) => { - panic!("ConstEquate should not be emitted when `-Znext-solver` is active") - } - ty::PredicateKind::NormalizesTo(predicate) => { - self.compute_normalizes_to_goal(Goal { param_env, predicate }) - } - ty::PredicateKind::AliasRelate(lhs, rhs, direction) => self - .compute_alias_relate_goal(Goal { - param_env, - predicate: (lhs, rhs, direction), - }), - ty::PredicateKind::Ambiguous => { - self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) - } + self.enter_forall(kind, |ecx, kind| match kind { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => { + ecx.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r) } - } else { - self.enter_forall(kind, |ecx, kind| { - let goal = goal.with(ecx.cx(), ty::Binder::dummy(kind)); - ecx.add_goal(GoalSource::InstantiateHigherRanked, goal); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }) - } + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => { + ecx.compute_host_effect_goal(Goal { param_env, predicate }) + } + ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => { + ecx.compute_projection_goal(Goal { param_env, predicate }) + } + ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => { + ecx.compute_type_outlives_goal(Goal { param_env, predicate }) + } + ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => { + ecx.compute_region_outlives_goal(Goal { param_env, predicate }) + } + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { + ecx.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) }) + } + ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => { + ecx.compute_unstable_feature_goal(param_env, symbol) + } + ty::PredicateKind::Subtype(predicate) => { + ecx.compute_subtype_goal(Goal { param_env, predicate }) + } + ty::PredicateKind::Coerce(predicate) => { + ecx.compute_coerce_goal(Goal { param_env, predicate }) + } + ty::PredicateKind::DynCompatible(trait_def_id) => { + ecx.compute_dyn_compatible_goal(trait_def_id) + } + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { + ecx.compute_well_formed_goal(Goal { param_env, predicate: term }) + } + ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => { + ecx.compute_const_evaluatable_goal(Goal { param_env, predicate: ct }) + } + ty::PredicateKind::ConstEquate(_, _) => { + panic!("ConstEquate should not be emitted when `-Znext-solver` is active") + } + ty::PredicateKind::NormalizesTo(predicate) => { + ecx.compute_normalizes_to_goal(Goal { param_env, predicate }) + } + ty::PredicateKind::AliasRelate(lhs, rhs, direction) => { + ecx.compute_alias_relate_goal(Goal { param_env, predicate: (lhs, rhs, direction) }) + } + ty::PredicateKind::Ambiguous => { + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } + }) } // Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning @@ -1528,7 +1515,7 @@ pub fn evaluate_root_goal_for_proof_tree_raw_provider< let mut inspect = inspect::ProofTreeBuilder::new(); let canonical_result = SearchGraph::::evaluate_root_goal_for_proof_tree( cx, - cx.recursion_limit(), + cx.recursion_limit() * 2, canonical_goal, &mut inspect, ); diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index 109c8476ccb16..ea45d50969909 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -99,19 +99,23 @@ where response_no_constraints(cx, input, Certainty::overflow(false)) } - fn is_ambiguous_result(result: QueryResult) -> bool { - result.is_ok_and(|response| { - has_no_inference_or_external_constraints(response) + fn is_ambiguous_result(result: QueryResult) -> Option { + result.ok().and_then(|response| { + if has_no_inference_or_external_constraints(response) && matches!(response.value.certainty, Certainty::Maybe { .. }) + { + Some(response.value.certainty) + } else { + None + } }) } fn propagate_ambiguity( cx: I, for_input: CanonicalInput, - from_result: QueryResult, + certainty: Certainty, ) -> QueryResult { - let certainty = from_result.unwrap().value.certainty; response_no_constraints(cx, for_input, certainty) } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index d1426ff55fbd6..dc9cfb37f0afb 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1058,7 +1058,7 @@ pub struct NextSolverConfig { pub coherence: bool = true, /// Whether the new trait solver should be enabled everywhere. /// This is only `true` if `coherence` is also enabled. - pub globally: bool = false, + pub globally: bool = true, } #[derive(Clone)] diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index bff4f6ce3fc6b..f806dd130b955 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -10,8 +10,8 @@ use rustc_infer::traits::{ FromSolverError, PredicateObligation, PredicateObligations, TraitEngine, }; use rustc_middle::ty::{ - self, DelayedSet, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, - TypingMode, + self, DelayedSet, Ty, TyCtxt, TyVid, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + TypeVisitor, TypingMode, }; use rustc_next_trait_solver::delegate::SolverDelegate as _; use rustc_next_trait_solver::solve::{ @@ -85,8 +85,27 @@ impl<'tcx> ObligationStorage<'tcx> { obligations.extend(self.overflowed.iter().cloned()); obligations } + fn clone_pending_potentially_referencing_sub_root( + &self, + vid: TyVid, + ) -> PredicateObligations<'tcx> { + let mut obligations: PredicateObligations<'tcx> = self + .pending + .iter() + .filter(|(_, stalled_on)| { + if let Some(stalled_on) = stalled_on { + stalled_on.sub_roots.iter().any(|&r| r == vid) + } else { + true + } + }) + .map(|(o, _)| o.clone()) + .collect(); + obligations.extend(self.overflowed.iter().cloned()); + obligations + } - fn drain_pending( + fn drain_pending_ignoring_overflowed( &mut self, cond: impl Fn(&PredicateObligation<'tcx>) -> bool, ) -> PendingObligations<'tcx> { @@ -184,7 +203,9 @@ where let mut errors = Vec::new(); loop { let mut any_changed = false; - for (mut obligation, stalled_on) in self.obligations.drain_pending(|_| true) { + for (mut obligation, stalled_on) in + self.obligations.drain_pending_ignoring_overflowed(|_| true) + { if !infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) { self.obligations.on_fulfillment_overflow(infcx); // Only return true errors that we have accumulated while processing. @@ -277,6 +298,12 @@ where fn pending_obligations(&self) -> PredicateObligations<'tcx> { self.obligations.clone_pending() } + fn pending_obligations_potentially_referencing_sub_root( + &self, + vid: ty::TyVid, + ) -> PredicateObligations<'tcx> { + self.obligations.clone_pending_potentially_referencing_sub_root(vid) + } fn drain_stalled_obligations_for_coroutines( &mut self, @@ -297,7 +324,7 @@ where } self.obligations - .drain_pending(|obl| { + .drain_pending_ignoring_overflowed(|obl| { infcx.probe(|_| { infcx .visit_proof_tree( diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index eef0ddcbf5965..598de27dfd3cb 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -231,7 +231,6 @@ impl<'tcx> BestObligation<'tcx> { nested_goal.source(), GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition - | GoalSource::InstantiateHigherRanked | GoalSource::AliasWellFormed ) && nested_goal.result().is_err() }, @@ -523,10 +522,6 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { )); impl_where_bound_count += 1; } - // Skip over a higher-ranked predicate. - (_, GoalSource::InstantiateHigherRanked) => { - obligation = self.obligation.clone(); - } (ChildMode::PassThrough, _) | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => { obligation = make_obligation(self.obligation.cause.clone()); diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index c010add0fc50f..de19319f12cbd 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -317,6 +317,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { self.depth } + pub fn orig_values(&self) -> &[ty::GenericArg<'tcx>] { + &self.orig_values + } + fn candidates_recur( &'a self, candidates: &mut Vec>, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 8e8c7dd7c9d48..ee0f31a2e885c 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -688,9 +688,10 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { // For bound predicates we simply call `infcx.enter_forall` // and then prove the resulting predicate as a nested goal. let Goal { param_env, predicate } = goal.goal(); - let trait_ref = match predicate.kind().no_bound_vars() { - Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref, - Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj))) + let predicate_kind = goal.infcx().enter_forall_and_leak_universe(predicate.kind()); + let trait_ref = match predicate_kind { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.trait_ref, + ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) if matches!( infcx.tcx.def_kind(proj.projection_term.def_id), DefKind::AssocTy | DefKind::AssocConst diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index f933423197df3..4b6349e2f4269 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -11,7 +11,7 @@ use crate::inherent::*; use crate::ir_print::IrPrint; use crate::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; use crate::relate::Relate; -use crate::solve::{CanonicalInput, ExternalConstraintsData, QueryResult, inspect}; +use crate::solve::{CanonicalInput, Certainty, ExternalConstraintsData, QueryResult, inspect}; use crate::visit::{Flags, TypeVisitable}; use crate::{self as ty, CanonicalParamEnvCacheEntry, search_graph}; @@ -550,6 +550,7 @@ impl CollectAndApply for Result { impl search_graph::Cx for I { type Input = CanonicalInput; type Result = QueryResult; + type AmbiguityInfo = Certainty; type DepNodeIndex = I::DepNodeIndex; type Tracked = I::Tracked; diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 8a41c99aeaae1..b2a871a21149e 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -40,6 +40,7 @@ pub use global_cache::GlobalCache; pub trait Cx: Copy { type Input: Debug + Eq + Hash + Copy; type Result: Debug + Eq + Hash + Copy; + type AmbiguityInfo: Debug + Eq + Hash + Copy; type DepNodeIndex; type Tracked: Debug; @@ -96,11 +97,13 @@ pub trait Delegate: Sized { input: ::Input, ) -> ::Result; - fn is_ambiguous_result(result: ::Result) -> bool; + fn is_ambiguous_result( + result: ::Result, + ) -> Option<::AmbiguityInfo>; fn propagate_ambiguity( cx: Self::Cx, for_input: ::Input, - from_result: ::Result, + ambiguity_info: ::AmbiguityInfo, ) -> ::Result; fn compute_goal( @@ -913,9 +916,9 @@ impl, X: Cx> SearchGraph { /// heads from the stack. This may not necessarily mean that we've actually /// reached a fixpoint for that cycle head, which impacts the way we rebase /// provisional cache entries. -enum RebaseReason { +enum RebaseReason { NoCycleUsages, - Ambiguity, + Ambiguity(X::AmbiguityInfo), Overflow, /// We've actually reached a fixpoint. /// @@ -951,7 +954,7 @@ impl, X: Cx> SearchGraph { &mut self, cx: X, stack_entry: &StackEntry, - rebase_reason: RebaseReason, + rebase_reason: RebaseReason, ) { let popped_head_index = self.stack.next_index(); #[allow(rustc::potential_query_instability)] @@ -969,10 +972,6 @@ impl, X: Cx> SearchGraph { return true; }; - let Some(new_highest_head_index) = heads.opt_highest_cycle_head_index() else { - return false; - }; - // We're rebasing an entry `e` over a head `p`. This head // has a number of own heads `h` it depends on. // @@ -1033,8 +1032,8 @@ impl, X: Cx> SearchGraph { // is not actually equal to the final provisional result. We // need to discard the provisional cache entry in this case. RebaseReason::NoCycleUsages => return false, - RebaseReason::Ambiguity => { - *result = D::propagate_ambiguity(cx, input, *result); + RebaseReason::Ambiguity(info) => { + *result = D::propagate_ambiguity(cx, input, info); } RebaseReason::Overflow => *result = D::fixpoint_overflow_result(cx, input), RebaseReason::ReachedFixpoint(None) => {} @@ -1046,6 +1045,10 @@ impl, X: Cx> SearchGraph { }; } + let Some(new_highest_head_index) = heads.opt_highest_cycle_head_index() else { + return false; + }; + // We now care about the path from the next highest cycle head to the // provisional cache entry. *path_from_head = path_from_head.extend(Self::cycle_path_kind( @@ -1268,6 +1271,7 @@ impl, X: Cx> SearchGraph { } /// Whether we've reached a fixpoint when evaluating a cycle head. + #[instrument(level = "trace", skip(self, stack_entry), ret)] fn reached_fixpoint( &mut self, stack_entry: &StackEntry, @@ -1355,8 +1359,12 @@ impl, X: Cx> SearchGraph { // As we only get to this branch if we haven't yet reached a fixpoint, // we also taint all provisional cache entries which depend on the // current goal. - if D::is_ambiguous_result(result) { - self.rebase_provisional_cache_entries(cx, &stack_entry, RebaseReason::Ambiguity); + if let Some(info) = D::is_ambiguous_result(result) { + self.rebase_provisional_cache_entries( + cx, + &stack_entry, + RebaseReason::Ambiguity(info), + ); return EvaluationResult::finalize(stack_entry, encountered_overflow, result); }; diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 9d9a8e4984786..752a9c05920c4 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -78,8 +78,6 @@ pub enum GoalSource { ImplWhereBound, /// Const conditions that need to hold for `[const]` alias bounds to hold. AliasBoundConstCondition, - /// Instantiating a higher-ranked goal and re-proving it. - InstantiateHigherRanked, /// Predicate required for an alias projection to be well-formed. /// This is used in three places: /// 1. projecting to an opaque whose hidden type is already registered in diff --git a/tests/ui/closures/deduce-signature/deduce-signature-infer-vars.rs b/tests/ui/closures/deduce-signature/deduce-signature-infer-vars.rs new file mode 100644 index 0000000000000..8c5ddb4c24e4a --- /dev/null +++ b/tests/ui/closures/deduce-signature/deduce-signature-infer-vars.rs @@ -0,0 +1,40 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// Regression test for an issue found in #146720. + +trait Trait { + type Assoc; +} + +struct W(T); +impl Trait for W +where + u32: Trait, +{ + type Assoc = T; +} + +impl Trait for (T,) { + type Assoc = T; +} + +impl Trait for u32 { + type Assoc = u32; +} + +fn foo(_: impl FnOnce(T::Assoc)) {} + +fn main() { + // The closure signature is `fn( as Trait>::Assoc)`. + // Normalizing it results in `?t` with `u32: Trait::Assoc>`. + // Equating `?t` with the argument pattern constrains it to `(?t,)`, at + // which point the `u32: Trait::Assoc>` obligations constrains + // `(?t,)` to `(u32,)`. + // + // This breaks when fudging inference to replace `?t` with an unconstrained + // infer var. + foo::>(|(field,)| { let _ = field.count_ones(); }) +} diff --git a/tests/ui/closures/deduce-signature/higher-ranked-alias-norm-to-hr.current_ambig.stderr b/tests/ui/closures/deduce-signature/higher-ranked-alias-norm-to-hr.current_ambig.stderr new file mode 100644 index 0000000000000..db1165b4701e6 --- /dev/null +++ b/tests/ui/closures/deduce-signature/higher-ranked-alias-norm-to-hr.current_ambig.stderr @@ -0,0 +1,49 @@ +error: implementation of `Foo` is not general enough + --> $DIR/higher-ranked-alias-norm-to-hr.rs:23:5 + | +LL | needs_super(|_| {}); + | ^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `{closure@$DIR/higher-ranked-alias-norm-to-hr.rs:23:17: 23:20}` must implement `Foo<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` + +error: implementation of `Fn` is not general enough + --> $DIR/higher-ranked-alias-norm-to-hr.rs:23:5 + | +LL | needs_super(|_| {}); + | ^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough + | + = note: closure with signature `fn(&'2 u32)` must implement `Fn<(&'1 u32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 u32,)>`, for some specific lifetime `'2` + +error: implementation of `Foo` is not general enough + --> $DIR/higher-ranked-alias-norm-to-hr.rs:23:5 + | +LL | needs_super(|_| {}); + | ^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `{closure@$DIR/higher-ranked-alias-norm-to-hr.rs:23:17: 23:20}` must implement `Foo<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `FnOnce` is not general enough + --> $DIR/higher-ranked-alias-norm-to-hr.rs:23:5 + | +LL | needs_super(|_| {}); + | ^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` + +error: implementation of `Foo` is not general enough + --> $DIR/higher-ranked-alias-norm-to-hr.rs:23:5 + | +LL | needs_super(|_| {}); + | ^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `{closure@$DIR/higher-ranked-alias-norm-to-hr.rs:23:17: 23:20}` must implement `Foo<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/closures/deduce-signature/higher-ranked-alias-norm-to-hr.next_ambig.stderr b/tests/ui/closures/deduce-signature/higher-ranked-alias-norm-to-hr.next_ambig.stderr new file mode 100644 index 0000000000000..850526c3c6220 --- /dev/null +++ b/tests/ui/closures/deduce-signature/higher-ranked-alias-norm-to-hr.next_ambig.stderr @@ -0,0 +1,51 @@ +error[E0277]: expected a `Fn(&'a u32)` closure, found `{closure@$DIR/higher-ranked-alias-norm-to-hr.rs:23:17: 23:20}` + --> $DIR/higher-ranked-alias-norm-to-hr.rs:23:17 + | +LL | needs_super(|_| {}); + | ----------- ^^^^^^ expected an `Fn(&'a u32)` closure, found `{closure@$DIR/higher-ranked-alias-norm-to-hr.rs:23:17: 23:20}` + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> Fn(&'a u32)` is not implemented for closure `{closure@$DIR/higher-ranked-alias-norm-to-hr.rs:23:17: 23:20}` + = note: expected a closure with signature `for<'a> fn(&'a _)` + found a closure with signature `fn(&_)` +note: this is a known limitation of the trait solver that will be lifted in the future + --> $DIR/higher-ranked-alias-norm-to-hr.rs:23:17 + | +LL | needs_super(|_| {}); + | ------------^^^---- + | | | + | | the trait solver is unable to infer the generic types that should be inferred from this argument + | add turbofish arguments to this call to specify the types manually, even if it's redundant +note: required by a bound in `needs_super` + --> $DIR/higher-ranked-alias-norm-to-hr.rs:17:19 + | +LL | fn needs_super Fn(>::Input) + for<'a> Foo<'a>>(_: F) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `needs_super` + +error[E0277]: the trait bound `for<'a> {closure@$DIR/higher-ranked-alias-norm-to-hr.rs:23:17: 23:20}: Foo<'a>` is not satisfied + --> $DIR/higher-ranked-alias-norm-to-hr.rs:23:17 + | +LL | needs_super(|_| {}); + | ----------- ^^^^^^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> Foo<'a>` is not implemented for closure `{closure@$DIR/higher-ranked-alias-norm-to-hr.rs:23:17: 23:20}` +note: this is a known limitation of the trait solver that will be lifted in the future + --> $DIR/higher-ranked-alias-norm-to-hr.rs:23:17 + | +LL | needs_super(|_| {}); + | ------------^^^---- + | | | + | | the trait solver is unable to infer the generic types that should be inferred from this argument + | add turbofish arguments to this call to specify the types manually, even if it's redundant +note: required by a bound in `needs_super` + --> $DIR/higher-ranked-alias-norm-to-hr.rs:17:55 + | +LL | fn needs_super Fn(>::Input) + for<'a> Foo<'a>>(_: F) {} + | ^^^^^^^^^^^^^^^ required by this bound in `needs_super` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/deduce-signature/higher-ranked-alias-norm-to-hr.rs b/tests/ui/closures/deduce-signature/higher-ranked-alias-norm-to-hr.rs new file mode 100644 index 0000000000000..cc724ecd602d7 --- /dev/null +++ b/tests/ui/closures/deduce-signature/higher-ranked-alias-norm-to-hr.rs @@ -0,0 +1,31 @@ +//@ revisions: current_ok next_ok current_ambig next_ambig +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next_ok] compile-flags: -Znext-solver +//@[next_ambig] compile-flags: -Znext-solver +//@[current_ok] check-pass +//@[next_ok] check-pass + +// Regression test for trait-system-refactor-initiative#191. +trait Foo<'a> { + type Input; +} + +impl<'a, F: Fn(&'a u32)> Foo<'a> for F { + type Input = &'a u32; +} + +fn needs_super Fn(>::Input) + for<'a> Foo<'a>>(_: F) {} + +fn main() { + #[cfg(any(current_ok, next_ok))] + needs_super(|_: &u32| {}); + #[cfg(any(current_ambig, next_ambig))] + needs_super(|_| {}); + //[next_ambig]~^ ERROR expected a `Fn(&'a u32)` closure, found + //[next_ambig]~| ERROR the trait bound + //[current_ambig]~^^^ ERROR implementation of `Foo` is not general enough + //[current_ambig]~| ERROR implementation of `Fn` is not general enough + //[current_ambig]~| ERROR implementation of `Foo` is not general enough + //[current_ambig]~| ERROR implementation of `FnOnce` is not general enough + //[current_ambig]~| ERROR implementation of `Foo` is not general enough +} diff --git a/tests/ui/closures/deduce-signature/higher-ranked-alias-norm-to-non-hr.rs b/tests/ui/closures/deduce-signature/higher-ranked-alias-norm-to-non-hr.rs new file mode 100644 index 0000000000000..5fd95d0d8f1ea --- /dev/null +++ b/tests/ui/closures/deduce-signature/higher-ranked-alias-norm-to-non-hr.rs @@ -0,0 +1,24 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#191. + +trait Indir: FnOnce(T) -> Self::Ret { + type Ret; +} +impl Indir for F where F: FnOnce(T) -> R { + type Ret = R; +} + +trait Mirror { + type Assoc<'a>; +} + +fn needs(_: impl for<'a> Indir>) {} + +fn test() where for<'a> T: Mirror = i32> { + needs::(|x| { x.to_string(); }); +} +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr index 22673cef64079..c92854b92f9d3 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr @@ -12,7 +12,7 @@ LL | impl Trait for Box {} | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` | = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` - = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<_>` + = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box< as WithAssoc<'a>>::Assoc>` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 52794b19945b6..59a949c506820 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -1,5 +1,3 @@ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:32:1 | diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index 9fa443eefb3dc..f5c9c6ec8cd90 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -1,5 +1,3 @@ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:32:1 | diff --git a/tests/crashes/140609.rs b/tests/ui/const-generics/generic_const_exprs/negative-coherence-ice-140609.rs similarity index 86% rename from tests/crashes/140609.rs rename to tests/ui/const-generics/generic_const_exprs/negative-coherence-ice-140609.rs index ee8a4bb30489f..1b02b874ed898 100644 --- a/tests/crashes/140609.rs +++ b/tests/ui/const-generics/generic_const_exprs/negative-coherence-ice-140609.rs @@ -1,6 +1,7 @@ -//@ known-bug: #140609 +//@ check-pass #![feature(with_negative_coherence)] #![feature(generic_const_exprs)] +#![allow(incomplete_features)] #![crate_type = "lib"] trait Trait {} struct A; diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.next.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.next.stderr deleted file mode 100644 index 90391b7b86b5c..0000000000000 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.next.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0277]: the trait bound `for<'a> &'a &T: Trait` is not satisfied - --> $DIR/candidate-from-env-universe-err-1.rs:27:16 - | -LL | hr_bound::<&T>(); - | ^^ the trait `for<'a> Trait` is not implemented for `&'a &T` - | -note: required by a bound in `hr_bound` - --> $DIR/candidate-from-env-universe-err-1.rs:14:20 - | -LL | fn hr_bound() - | -------- required by a bound in this function -LL | where -LL | for<'a> &'a T: Trait, - | ^^^^^ required by this bound in `hr_bound` -help: consider removing the leading `&`-reference - | -LL - hr_bound::<&T>(); -LL + hr_bound::(); - | - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.rs b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.rs index bd251216162db..e7e396aa71f17 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.rs +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.rs @@ -1,6 +1,7 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[old] check-pass +//@ check-pass // cc #119820 @@ -25,7 +26,6 @@ where // the leak check both candidates may apply and we prefer the // `param_env` candidate in winnowing. hr_bound::<&T>(); - //[next]~^ ERROR the trait bound `for<'a> &'a &T: Trait` is not satisfied } fn main() {} diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr deleted file mode 100644 index 0f5a9de7ab854..0000000000000 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0277]: the trait bound `for<'a> T: Trait<'a, '_>` is not satisfied - --> $DIR/candidate-from-env-universe-err-2.rs:15:15 - | -LL | impl_hr::(); - | ^ the trait `for<'a> Trait<'a, '_>` is not implemented for `T` - | -note: required by a bound in `impl_hr` - --> $DIR/candidate-from-env-universe-err-2.rs:12:19 - | -LL | fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {} - | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impl_hr` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.rs b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.rs index 0132b7db60574..96c6f95329aff 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.rs +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.rs @@ -1,6 +1,7 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[current] check-pass +//@ check-pass // cc #119820 @@ -13,7 +14,6 @@ fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {} fn not_hr<'a, T: for<'b> Trait<'a, 'b> + OtherTrait<'static>>() { impl_hr::(); - //[next]~^ ERROR the trait bound `for<'a> T: Trait<'a, '_>` is not satisfied } fn main() {} diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr index c8394575e71de..395dd068e2371 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr @@ -7,7 +7,7 @@ LL | projection_bound::(); = note: expected associated type `>::Assoc` found associated type `>::Assoc` note: the lifetime requirement is introduced here - --> $DIR/candidate-from-env-universe-err-project.rs:18:42 + --> $DIR/candidate-from-env-universe-err-project.rs:19:42 | LL | fn projection_bound Trait<'a, Assoc = usize>>() {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr index 468dc3b082e5c..ddfc94da1354c 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr @@ -1,26 +1,14 @@ -error[E0277]: the trait bound `for<'a> T: Trait<'a>` is not satisfied - --> $DIR/candidate-from-env-universe-err-project.rs:28:19 - | -LL | trait_bound::(); - | ^ the trait `for<'a> Trait<'a>` is not implemented for `T` - | -note: required by a bound in `trait_bound` - --> $DIR/candidate-from-env-universe-err-project.rs:17:19 - | -LL | fn trait_bound Trait<'a>>() {} - | ^^^^^^^^^^^^^^^^^ required by this bound in `trait_bound` - -error[E0277]: the trait bound `for<'a> T: Trait<'a>` is not satisfied +error[E0271]: type mismatch resolving `>::Assoc == usize` --> $DIR/candidate-from-env-universe-err-project.rs:38:24 | LL | projection_bound::(); - | ^ the trait `for<'a> Trait<'a>` is not implemented for `T` + | ^ types differ | note: required by a bound in `projection_bound` - --> $DIR/candidate-from-env-universe-err-project.rs:18:24 + --> $DIR/candidate-from-env-universe-err-project.rs:19:42 | LL | fn projection_bound Trait<'a, Assoc = usize>>() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `projection_bound` + | ^^^^^^^^^^^^^ required by this bound in `projection_bound` error: higher-ranked subtype error --> $DIR/candidate-from-env-universe-err-project.rs:52:30 @@ -36,6 +24,6 @@ LL | let _higher_ranked_norm: for<'a> fn(>::Assoc) = |_| (); | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs index d70e392238218..dd6da62a47272 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs @@ -1,4 +1,5 @@ //@ revisions: next current +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // cc #119820 the behavior is inconsistent as we discard the where-bound @@ -20,13 +21,12 @@ fn projection_bound Trait<'a, Assoc = usize>>() {} // We use a function with a trivial where-bound which is more // restrictive than the impl. fn function1>() { - // err + // ok // // Proving `for<'a> T: Trait<'a>` using the where-bound does not // result in a leak check failure even though it does not apply. // We prefer env candidates over impl candidatescausing this to succeed. trait_bound::(); - //[next]~^ ERROR the trait bound `for<'a> T: Trait<'a>` is not satisfied } fn function2>() { @@ -36,7 +36,7 @@ fn function2>() { // does not use the leak check when trying the where-bound, causing us // to prefer it over the impl, resulting in a placeholder error. projection_bound::(); - //[next]~^ ERROR the trait bound `for<'a> T: Trait<'a>` is not satisfied + //[next]~^ ERROR type mismatch resolving `>::Assoc == usize` //[current]~^^ ERROR mismatched types } diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.next.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.next.stderr deleted file mode 100644 index cb97bc4b8fc6e..0000000000000 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.next.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0283]: type annotations needed - --> $DIR/leak-check-in-selection-2.rs:17:5 - | -LL | impls_trait::<(), _>(); - | ^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_trait` - | -note: multiple `impl`s satisfying `for<'a> (): Trait<&'a str, _>` found - --> $DIR/leak-check-in-selection-2.rs:10:1 - | -LL | impl<'a> Trait<&'a str, &'a str> for () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | impl<'a> Trait<&'a str, String> for () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required by a bound in `impls_trait` - --> $DIR/leak-check-in-selection-2.rs:14:19 - | -LL | fn impls_trait Trait<&'a str, U>, U>() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls_trait` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.rs index 24e38ec45a2c4..365d743528448 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.rs +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.rs @@ -1,6 +1,7 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[old] check-pass +//@ check-pass // cc #119820 @@ -15,5 +16,4 @@ fn impls_trait Trait<&'a str, U>, U>() {} fn main() { impls_trait::<(), _>(); - //[next]~^ ERROR type annotations needed } diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr index 5be683cd3191b..622df3b00e595 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr @@ -1,22 +1,3 @@ -error[E0283]: type annotations needed - --> $DIR/leak-check-in-selection-3.rs:18:5 - | -LL | impls_leak::>(); - | ^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_leak` - | -note: multiple `impl`s satisfying `for<'a> Box<_>: Leak<'a>` found - --> $DIR/leak-check-in-selection-3.rs:9:1 - | -LL | impl Leak<'_> for Box {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | impl Leak<'static> for Box {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required by a bound in `impls_leak` - --> $DIR/leak-check-in-selection-3.rs:12:18 - | -LL | fn impls_leak Leak<'a>>() {} - | ^^^^^^^^^^^^^^^^ required by this bound in `impls_leak` - error[E0283]: type annotations needed --> $DIR/leak-check-in-selection-3.rs:35:5 | @@ -24,7 +5,7 @@ LL | impls_indirect_leak::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak` | note: multiple `impl`s satisfying `for<'a> Box<_>: Leak<'a>` found - --> $DIR/leak-check-in-selection-3.rs:9:1 + --> $DIR/leak-check-in-selection-3.rs:10:1 | LL | impl Leak<'_> for Box {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,6 +24,6 @@ note: required by a bound in `impls_indirect_leak` LL | fn impls_indirect_leak IndirectLeak<'a>>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls_indirect_leak` -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.old.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.old.stderr index 194571dd4a85b..a193ddd891691 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.old.stderr +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.old.stderr @@ -5,7 +5,7 @@ LL | impls_indirect_leak::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak` | note: multiple `impl`s satisfying `Box<_>: Leak<'_>` found - --> $DIR/leak-check-in-selection-3.rs:9:1 + --> $DIR/leak-check-in-selection-3.rs:10:1 | LL | impl Leak<'_> for Box {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.rs index 9aa1be57a4fb2..191528a15e659 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.rs +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // cc #119820, the behavior here is inconsistent, @@ -16,7 +17,6 @@ fn direct() { // The `Box` impls fails the leak check, // meaning that we apply the `Box` impl. impls_leak::>(); - //[next]~^ ERROR type annotations needed } trait IndirectLeak<'a> {} diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.next.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.next.stderr index a12e3312230af..77dec93d0617a 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.next.stderr +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.next.stderr @@ -1,18 +1,18 @@ error[E0283]: type annotations needed - --> $DIR/leak-check-in-selection-6-ambig-unify.rs:30:5 + --> $DIR/leak-check-in-selection-6-ambig-unify.rs:32:5 | LL | impls_trait::<(), _, _>() | ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_trait` | note: multiple `impl`s satisfying `(): Trait<_, _>` found - --> $DIR/leak-check-in-selection-6-ambig-unify.rs:26:1 + --> $DIR/leak-check-in-selection-6-ambig-unify.rs:28:1 | -LL | impl Trait for () where for<'b> (): LeakCheckFailure<'static, 'b, V> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Trait for () where for<'b> ((),): LeakCheckFailure<'static, 'b, V> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | impl Trait for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `impls_trait` - --> $DIR/leak-check-in-selection-6-ambig-unify.rs:28:19 + --> $DIR/leak-check-in-selection-6-ambig-unify.rs:30:19 | LL | fn impls_trait, U: Id, V>() {} | ^^^^^^^^^^^ required by this bound in `impls_trait` diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.old.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.old.stderr index a12e3312230af..77dec93d0617a 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.old.stderr +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.old.stderr @@ -1,18 +1,18 @@ error[E0283]: type annotations needed - --> $DIR/leak-check-in-selection-6-ambig-unify.rs:30:5 + --> $DIR/leak-check-in-selection-6-ambig-unify.rs:32:5 | LL | impls_trait::<(), _, _>() | ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_trait` | note: multiple `impl`s satisfying `(): Trait<_, _>` found - --> $DIR/leak-check-in-selection-6-ambig-unify.rs:26:1 + --> $DIR/leak-check-in-selection-6-ambig-unify.rs:28:1 | -LL | impl Trait for () where for<'b> (): LeakCheckFailure<'static, 'b, V> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Trait for () where for<'b> ((),): LeakCheckFailure<'static, 'b, V> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | impl Trait for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `impls_trait` - --> $DIR/leak-check-in-selection-6-ambig-unify.rs:28:19 + --> $DIR/leak-check-in-selection-6-ambig-unify.rs:30:19 | LL | fn impls_trait, U: Id, V>() {} | ^^^^^^^^^^^ required by this bound in `impls_trait` diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs index 592d581695e52..2a286b2dd7bd2 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // The new trait solver does not return region constraints if the goal @@ -21,9 +22,10 @@ impl Id for u16 {} trait LeakCheckFailure<'a, 'b, V: ?Sized> {} impl<'a, 'b: 'a, V: ?Sized + Ambig> LeakCheckFailure<'a, 'b, V> for () {} +impl<'a, 'b, V: ?Sized, T: LeakCheckFailure<'a, 'b, V>> LeakCheckFailure<'a, 'b, V> for (T,) {} trait Trait {} -impl Trait for () where for<'b> (): LeakCheckFailure<'static, 'b, V> {} +impl Trait for () where for<'b> ((),): LeakCheckFailure<'static, 'b, V> {} impl Trait for () {} fn impls_trait, U: Id, V>() {} fn main() { diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-7-coherence.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-7-coherence.rs new file mode 100644 index 0000000000000..97837515ccbf9 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-7-coherence.rs @@ -0,0 +1,20 @@ +//@ check-pass + +// cc #119820 +struct W(T, U); + +trait Trait {} +// using this impl results in a higher-ranked region error. +impl<'a> Trait> for () {} +impl<'a> Trait> for () {} + +trait NotString {} +impl NotString for &str {} +impl NotString for u32 {} + + +trait Overlap {} +impl Trait>, U> Overlap for T {} +impl Overlap for () {} + +fn main() {} diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index b27a2dcceb138..1e111b3e199f8 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -1,4 +1,3 @@ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a))], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied --> $DIR/structually-relate-aliases.rs:13:36 | diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed index ba46a447802c8..1c45a2c0adb3e 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed @@ -8,6 +8,5 @@ fn main() { //[next]~^^ ERROR expected a `FnMut(& as Iterator>::Item)` closure, found let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments - //[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}` - //[next]~| ERROR expected a `FnMut(& as Iterator>::Item)` closure, found + //[next]~^^ ERROR expected a `FnMut(& as Iterator>::Item)` closure, found } diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr index 7912ed4d7071a..36e49c20c4331 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr @@ -12,12 +12,6 @@ LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error[E0271]: expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}` - --> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:24 - | -LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); - | ^^^^ expected `&&i32`, found integer - error[E0277]: expected a `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}` --> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:29 | @@ -32,7 +26,6 @@ LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs index 0fd56707763e9..20d6fed3b35b8 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs @@ -8,6 +8,5 @@ fn main() { //[next]~^^ ERROR expected a `FnMut(& as Iterator>::Item)` closure, found let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments - //[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}` - //[next]~| ERROR expected a `FnMut(& as Iterator>::Item)` closure, found + //[next]~^^ ERROR expected a `FnMut(& as Iterator>::Item)` closure, found } diff --git a/tests/ui/traits/next-solver/cycles/forced_ambiguity-use-head-maybe-cause.rs b/tests/ui/traits/next-solver/cycles/forced_ambiguity-use-head-maybe-cause.rs new file mode 100644 index 0000000000000..aa5893d621cdb --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/forced_ambiguity-use-head-maybe-cause.rs @@ -0,0 +1,44 @@ +//@ compile-flags: -Znext-solver +#![feature(rustc_attrs)] +#![rustc_no_implicit_bounds] + +// A regression test making sure that when forcing dependent +// provisional cache entries to ambiguous, we use the `MaybeCause` +// of the cycle head. We ended up trying to use the current result +// of the provisional cache entry, which is incorrect and caused an +// ICE when trying to unwrap it. + +struct Root(T); +struct Head(T); +struct Error(T); +struct NotImplemented(T); + +#[rustc_coinductive] +trait Trait {} +impl Trait for Root +where + Head: Trait, +{} + +impl Trait for Head +where + Root: Trait, + T: Trait, // ambiguous +{} + +impl Trait for Head +where + Error: Trait, + NotImplemented: Trait, +{} + +impl Trait for Error +where + Head: Trait, + NotImplemented: Trait, +{} + +fn impls_trait() {} +fn main() { + impls_trait::>() //~ ERROR type annotations needed +} diff --git a/tests/ui/traits/next-solver/cycles/forced_ambiguity-use-head-maybe-cause.stderr b/tests/ui/traits/next-solver/cycles/forced_ambiguity-use-head-maybe-cause.stderr new file mode 100644 index 0000000000000..dd4049a66d0b4 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/forced_ambiguity-use-head-maybe-cause.stderr @@ -0,0 +1,27 @@ +error[E0283]: type annotations needed + --> $DIR/forced_ambiguity-use-head-maybe-cause.rs:43:19 + | +LL | impls_trait::>() + | ^^^^^^^ cannot infer type for struct `Head<_>` + | + = note: cannot satisfy `Head<_>: Trait` + = help: the trait `Trait` is implemented for `Head` +note: required for `Root<_>` to implement `Trait` + --> $DIR/forced_ambiguity-use-head-maybe-cause.rs:18:9 + | +LL | impl Trait for Root + | ^^^^^ ^^^^^^^ +LL | where +LL | Head: Trait, + | ----- unsatisfied trait bound introduced here + = note: 8 redundant requirements hidden + = note: required for `Root<_>` to implement `Trait` +note: required by a bound in `impls_trait` + --> $DIR/forced_ambiguity-use-head-maybe-cause.rs:41:19 + | +LL | fn impls_trait() {} + | ^^^^^ required by this bound in `impls_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index ce4f742a3fa97..4eda74e8cdb3a 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -25,7 +25,6 @@ help: this trait has no implementations, consider adding one LL | trait ToUnit<'a> { | ^^^^^^^^^^^^^^^^ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a)), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } error[E0277]: the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied --> $DIR/issue-118950-root-region.rs:19:9 |