From 8ebb3d49e41ce0764b71fb9b3e7ec219f5a2fbda Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 27 Jun 2023 23:04:54 +0200 Subject: [PATCH 01/10] rename `structurally_resolved_type` --- compiler/rustc_hir_typeck/src/callee.rs | 4 ++-- compiler/rustc_hir_typeck/src/cast.rs | 4 ++-- compiler/rustc_hir_typeck/src/expr.rs | 16 ++++++++-------- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 4 ++-- compiler/rustc_hir_typeck/src/method/confirm.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 8 ++++---- compiler/rustc_hir_typeck/src/place_op.rs | 2 +- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 9da72aae77660..be908c41c94df 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -89,7 +89,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => self.check_expr(callee_expr), }; - let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty); + let expr_ty = self.structurally_resolve_type(call_expr.span, original_callee_ty); let mut autoderef = self.autoderef(callee_expr.span, expr_ty); let mut result = None; @@ -138,7 +138,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { autoderef: &Autoderef<'a, 'tcx>, ) -> Option> { let adjusted_ty = - self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); + self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); // If the callee is a bare function or a closure, then we're all set. match *adjusted_ty.kind() { diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 7a1e830073a72..f1b3d13c24d3d 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -717,8 +717,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { #[instrument(skip(fcx), level = "debug")] pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) { - self.expr_ty = fcx.structurally_resolved_type(self.expr_span, self.expr_ty); - self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty); + self.expr_ty = fcx.structurally_resolve_type(self.expr_span, self.expr_ty); + self.cast_ty = fcx.structurally_resolve_type(self.cast_span, self.cast_ty); debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index f5be030c1a51d..52e3779cd41cf 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -380,7 +380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut oprnd_t = self.check_expr_with_expectation(&oprnd, expected_inner); if !oprnd_t.references_error() { - oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t); + oprnd_t = self.structurally_resolve_type(expr.span, oprnd_t); match unop { hir::UnOp::Deref => { if let Some(ty) = self.lookup_derefing(expr, oprnd, oprnd_t) { @@ -1266,13 +1266,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let rcvr_t = self.check_expr(&rcvr); // no need to check for bot/err -- callee does that - let rcvr_t = self.structurally_resolved_type(rcvr.span, rcvr_t); + let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t); let span = segment.ident.span; let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) { Ok(method) => { // We could add a "consider `foo::`" suggestion here, but I wasn't able to - // trigger this codepath causing `structurally_resolved_type` to emit an error. + // trigger this codepath causing `structurally_resolve_type` to emit an error. self.write_method_call(expr.hir_id, method); Ok(method) @@ -2252,7 +2252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { debug!("check_field(expr: {:?}, base: {:?}, field: {:?})", expr, base, field); let base_ty = self.check_expr(base); - let base_ty = self.structurally_resolved_type(base.span, base_ty); + let base_ty = self.structurally_resolve_type(base.span, base_ty); let mut private_candidate = None; let mut autoderef = self.autoderef(expr.span, base_ty); while let Some((deref_base_ty, _)) = autoderef.next() { @@ -2300,7 +2300,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => {} } } - self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); + self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); if let Some((adjustments, did)) = private_candidate { // (#90483) apply adjustments to avoid ExprUseVisitor from @@ -2857,7 +2857,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if idx_t.references_error() { idx_t } else { - let base_t = self.structurally_resolved_type(base.span, base_t); + let base_t = self.structurally_resolve_type(base.span, base_t); match self.lookup_indexing(expr, base, base_t, idx, idx_t) { Some((index_ty, element_ty)) => { // two-phase not needed because index_ty is never mutable @@ -3084,7 +3084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // allows them to be inferred based on how they are used later in the // function. if is_input { - let ty = self.structurally_resolved_type(expr.span, ty); + let ty = self.structurally_resolve_type(expr.span, ty); match *ty.kind() { ty::FnDef(..) => { let fnptr_ty = self.tcx.mk_fn_ptr(ty.fn_sig(self.tcx)); @@ -3142,7 +3142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut current_container = container; for &field in fields { - let container = self.structurally_resolved_type(expr.span, current_container); + let container = self.structurally_resolve_type(expr.span, current_container); match container.kind() { ty::Adt(container_def, substs) if !container_def.is_enum() => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 0ee87173a36c4..b1c480e0ded4e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1473,7 +1473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// If no resolution is possible, then an error is reported. /// Numeric inference variables may be left unresolved. - pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { + pub fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { let mut ty = self.resolve_vars_with_obligations(ty); if self.next_trait_solver() diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index dacd5559c71fa..7ce568ca48bc5 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -184,7 +184,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments { - let tuple_type = self.structurally_resolved_type(call_span, formal_input_tys[0]); + let tuple_type = self.structurally_resolve_type(call_span, formal_input_tys[0]); match tuple_type.kind() { // We expected a tuple and got a tuple ty::Tuple(arg_types) => { @@ -412,7 +412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // There are a few types which get autopromoted when passed via varargs // in C but we just error out instead and require explicit casts. - let arg_ty = self.structurally_resolved_type(arg.span, arg_ty); + let arg_ty = self.structurally_resolve_type(arg.span, arg_ty); match arg_ty.kind() { ty::Float(ty::FloatTy::F32) => { variadic_error(tcx.sess, arg.span, arg_ty, "c_double"); diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 31894d25b60dc..966cd6a389e27 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -179,7 +179,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { assert_eq!(n, pick.autoderefs); let mut adjustments = self.adjust_steps(&autoderef); - let mut target = self.structurally_resolved_type(autoderef.span(), ty); + let mut target = self.structurally_resolve_type(autoderef.span(), ty); match pick.autoref_or_ptr_adjustment { Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, unsize }) => { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 35d70968ce7dd..4c41fa3801218 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -451,7 +451,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { // Ended up encountering a type variable when doing autoderef, // but it may not be a type variable after processing obligations - // in our local `FnCtxt`, so don't call `structurally_resolved_type`. + // in our local `FnCtxt`, so don't call `structurally_resolve_type`. let ty = &bad_ty.ty; let ty = self .probe_instantiate_query_response(span, &orig_values, ty) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 9c989d3b4b250..96d03b471252f 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -393,7 +393,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // They can denote both statically and dynamically-sized byte arrays. let mut pat_ty = ty; if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind { - let expected = self.structurally_resolved_type(span, expected); + let expected = self.structurally_resolve_type(span, expected); if let ty::Ref(_, inner_ty, _) = expected.kind() && matches!(inner_ty.kind(), ty::Slice(_)) { @@ -501,7 +501,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This check is needed if both sides are inference variables. // We require types to be resolved here so that we emit inference failure // rather than "_ is not a char or numeric". - let ty = self.structurally_resolved_type(span, expected); + let ty = self.structurally_resolve_type(span, expected); if !(ty.is_numeric() || ty.is_char() || ty.references_error()) { if let Some((ref mut fail, _, _)) = lhs { *fail = true; @@ -1289,7 +1289,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut expected_len = elements.len(); if ddpos.as_opt_usize().is_some() { // Require known type only when `..` is present. - if let ty::Tuple(tys) = self.structurally_resolved_type(span, expected).kind() { + if let ty::Tuple(tys) = self.structurally_resolve_type(span, expected).kind() { expected_len = tys.len(); } } @@ -2042,7 +2042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { def_bm: BindingMode, ti: TopInfo<'tcx>, ) -> Ty<'tcx> { - let expected = self.structurally_resolved_type(span, expected); + let expected = self.structurally_resolve_type(span, expected); let (element_ty, opt_slice_ty, inferred) = match *expected.kind() { // An array, so we might have something like `let [a, b, c] = [0, 1, 2];`. ty::Array(element_ty, len) => { diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index e2b1dc007ba6d..b8aaaebb85e17 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -107,7 +107,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { index_expr: &hir::Expr<'_>, ) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { let adjusted_ty = - self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); + self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); debug!( "try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \ index_ty={:?})", From bd0d533d230d7c14ab638c4ea2c580d0761e1426 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 27 Jun 2023 23:09:53 +0200 Subject: [PATCH 02/10] fix structurally relate for weak aliases --- compiler/rustc_middle/src/ty/relate.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 74a3bddf2fae7..85d09cfbc7266 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -544,17 +544,8 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( Ok(tcx.mk_fn_ptr(fty)) } - // these two are already handled downstream in case of lazy normalization - (&ty::Alias(ty::Projection, a_data), &ty::Alias(ty::Projection, b_data)) => { - let projection_ty = relation.relate(a_data, b_data)?; - Ok(tcx.mk_projection(projection_ty.def_id, projection_ty.substs)) - } - - (&ty::Alias(ty::Inherent, a_data), &ty::Alias(ty::Inherent, b_data)) => { - let alias_ty = relation.relate(a_data, b_data)?; - Ok(tcx.mk_alias(ty::Inherent, tcx.mk_alias_ty(alias_ty.def_id, alias_ty.substs))) - } - + // The substs of opaque types may not all be invariant, so we have + // to treat them separately from other aliases. ( &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }), &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }), @@ -571,6 +562,19 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( Ok(tcx.mk_opaque(a_def_id, substs)) } + // Alias tend to mostly already be handled downstream due to normalization. + (&ty::Alias(a_kind, a_data), &ty::Alias(b_kind, b_data)) => { + // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This if can be removed + // and the assert uncommented once the new desugaring is stable. + if a_kind == b_kind { + let alias_ty = relation.relate(a_data, b_data)?; + // assert_eq!(a_kind, b_kind); + Ok(tcx.mk_alias(a_kind, alias_ty)) + } else { + Err(TypeError::Sorts(expected_found(relation, a, b))) + } + } + _ => Err(TypeError::Sorts(expected_found(relation, a, b))), } } From 4d42de6d1bfaca5bb21f67c7eb926323c6e86e6c Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 27 Jun 2023 23:10:36 +0200 Subject: [PATCH 03/10] add instrument to `register_predicate_obligation` --- compiler/rustc_trait_selection/src/solve/fulfill.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index fc848fe30808f..d883e48771657 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -41,6 +41,7 @@ impl<'tcx> FulfillmentCtxt<'tcx> { } impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { + #[instrument(level = "debug", skip(self, _infcx))] fn register_predicate_obligation( &mut self, infcx: &InferCtxt<'tcx>, From 42067596c2c307e869052c91e1631e0f395a56b6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 27 Jun 2023 23:11:37 +0200 Subject: [PATCH 04/10] add deep normalization via the new solver --- compiler/rustc_infer/src/infer/at.rs | 1 + .../rustc_trait_selection/src/solve/mod.rs | 2 + .../src/solve/normalize.rs | 222 ++++++++++++++++++ .../rustc_trait_selection/src/traits/mod.rs | 2 + .../src/traits/project.rs | 46 +++- .../src/traits/query/normalize.rs | 14 +- 6 files changed, 281 insertions(+), 6 deletions(-) create mode 100644 compiler/rustc_trait_selection/src/solve/normalize.rs diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index f1a187d267760..433735e827bdd 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -40,6 +40,7 @@ pub enum DefineOpaqueTypes { No, } +#[derive(Clone, Copy)] pub struct At<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, pub cause: &'a ObligationCause<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 49fecedc0caa3..769d002fcc0cc 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -26,6 +26,7 @@ mod canonicalize; mod eval_ctxt; mod fulfill; pub mod inspect; +mod normalize; mod opaques; mod project_goals; mod search_graph; @@ -34,6 +35,7 @@ mod weak_types; pub use eval_ctxt::{EvalCtxt, InferCtxtEvalExt}; pub use fulfill::FulfillmentCtxt; +pub(crate) use normalize::deeply_normalize; #[derive(Debug, Clone, Copy)] enum SolverMode { diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs new file mode 100644 index 0000000000000..420a6ee8978ff --- /dev/null +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -0,0 +1,222 @@ +use crate::traits::error_reporting::TypeErrCtxtExt; +use crate::traits::query::evaluate_obligation::InferCtxtExt; +use crate::traits::{needs_normalization, TraitEngineExt as _}; +use crate::traits::{BoundVarReplacer, PlaceholderReplacer}; +use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_infer::infer::at::At; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::traits::TraitEngineExt; +use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine}; +use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use rustc_middle::traits::Reveal; +use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex}; +use rustc_middle::ty::{FallibleTypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::{TypeFoldable, TypeVisitableExt}; + +/// Deeply normalize all aliases in `value`. This does not handle inference and expects +/// its input to be already fully resolved. +pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable>>( + at: At<'_, 'tcx>, + value: T, +) -> Result>> { + let mut fulfill_cx = >::new(&at.infcx); + let mut folder = + NormalizationFolder { at, fulfill_cx: &mut *fulfill_cx, depth: 0, universes: Vec::new() }; + + value.try_fold_with(&mut folder) +} + +struct NormalizationFolder<'me, 'tcx> { + at: At<'me, 'tcx>, + fulfill_cx: &'me mut dyn TraitEngine<'tcx>, + depth: usize, + universes: Vec>, +} + +impl<'tcx> NormalizationFolder<'_, 'tcx> { + fn normalize_alias_ty( + &mut self, + alias: AliasTy<'tcx>, + ) -> Result, Vec>> { + let infcx = self.at.infcx; + let tcx = infcx.tcx; + let recursion_limit = tcx.recursion_limit(); + if !recursion_limit.value_within_limit(self.depth) { + self.at.infcx.err_ctxt().report_overflow_error( + &alias.to_ty(tcx), + self.at.cause.span, + true, + |_| {}, + ); + } + + self.depth += 1; + + let new_infer_ty = infcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::NormalizeProjectionType, + span: self.at.cause.span, + }); + let obligation = Obligation::new( + tcx, + self.at.cause.clone(), + self.at.param_env, + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: alias, + term: new_infer_ty.into(), + }), + ); + + // Do not emit an error if normalization is known to fail but instead + // keep the projection unnormalized. This is the case for projections + // with a `T: Trait` where-clause and opaque types outside of the defining + // scope. + let result = if infcx.predicate_may_hold(&obligation) { + self.fulfill_cx.register_predicate_obligation(infcx, obligation); + let errors = self.fulfill_cx.select_all_or_error(infcx); + if !errors.is_empty() { + return Err(errors); + } + let ty = infcx.resolve_vars_if_possible(new_infer_ty); + ty.try_fold_with(self)? + } else { + alias.to_ty(tcx).try_super_fold_with(self)? + }; + + self.depth -= 1; + Ok(result) + } + + fn normalize_unevaluated_const( + &mut self, + ty: Ty<'tcx>, + uv: ty::UnevaluatedConst<'tcx>, + ) -> Result, Vec>> { + let infcx = self.at.infcx; + let tcx = infcx.tcx; + let recursion_limit = tcx.recursion_limit(); + if !recursion_limit.value_within_limit(self.depth) { + self.at.infcx.err_ctxt().report_overflow_error( + &tcx.mk_const(uv, ty), + self.at.cause.span, + true, + |_| {}, + ); + } + + self.depth += 1; + + let new_infer_ct = infcx.next_const_var( + ty, + ConstVariableOrigin { + kind: ConstVariableOriginKind::MiscVariable, + span: self.at.cause.span, + }, + ); + let obligation = Obligation::new( + tcx, + self.at.cause.clone(), + self.at.param_env, + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: tcx.mk_alias_ty(uv.def, uv.substs), + term: new_infer_ct.into(), + }), + ); + + let result = if infcx.predicate_may_hold(&obligation) { + self.fulfill_cx.register_predicate_obligation(infcx, obligation); + let errors = self.fulfill_cx.select_all_or_error(infcx); + if !errors.is_empty() { + return Err(errors); + } + let ct = infcx.resolve_vars_if_possible(new_infer_ct); + ct.try_fold_with(self)? + } else { + tcx.mk_const(uv, ty).try_super_fold_with(self)? + }; + + self.depth -= 1; + Ok(result) + } +} + +impl<'tcx> FallibleTypeFolder> for NormalizationFolder<'_, 'tcx> { + type Error = Vec>; + + fn interner(&self) -> TyCtxt<'tcx> { + self.at.infcx.tcx + } + + fn try_fold_binder>>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> Result, Self::Error> { + self.universes.push(None); + let t = t.try_super_fold_with(self)?; + self.universes.pop(); + Ok(t) + } + + fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, Self::Error> { + let reveal = self.at.param_env.reveal(); + let infcx = self.at.infcx; + if !needs_normalization(&ty, reveal) { + return Ok(ty); + } + + let (kind, data) = match *ty.kind() { + ty::Alias(kind, alias_ty) => (kind, alias_ty), + _ => return ty.try_super_fold_with(self), + }; + + // We don't normalize opaque types unless we have + // `Reveal::All`, even if we're in the defining scope. + if matches!(kind, ty::Opaque) && reveal == Reveal::UserFacing { + return ty.try_super_fold_with(self); + } + + if data.has_escaping_bound_vars() { + let (data, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); + let result = ensure_sufficient_stack(|| self.normalize_alias_ty(data))?; + Ok(PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &mut self.universes, + result, + )) + } else { + ensure_sufficient_stack(|| self.normalize_alias_ty(data)) + } + } + + fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result, Self::Error> { + let reveal = self.at.param_env.reveal(); + let infcx = self.at.infcx; + if !needs_normalization(&ct, reveal) { + return Ok(ct); + } + + let uv = match ct.kind() { + ty::ConstKind::Unevaluated(ct) => ct, + _ => return ct.try_super_fold_with(self), + }; + + if uv.has_escaping_bound_vars() { + let (uv, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv); + let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct.ty(), uv))?; + Ok(PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &mut self.universes, + result, + )) + } else { + ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct.ty(), uv)) + } + } +} diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 5dc5ddbddbdb8..89aefc0de530d 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -40,6 +40,8 @@ use rustc_span::Span; use std::fmt::Debug; use std::ops::ControlFlow; +pub(crate) use self::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer}; + pub use self::FulfillmentErrorCode::*; pub use self::ImplSource::*; pub use self::ObligationCauseCode::*; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 8fd7733507438..e4eea14ef74f7 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -20,6 +20,7 @@ use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use crate::traits::error_reporting::TypeErrCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::select::ProjectionMatchesProjection; +use crate::traits::TraitEngineExt as _; use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorGuaranteed; @@ -28,7 +29,10 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::at::At; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_infer::infer::DefineOpaqueTypes; +use rustc_infer::traits::FulfillmentError; use rustc_infer::traits::ObligationCauseCode; +use rustc_infer::traits::TraitEngine; +use rustc_infer::traits::TraitEngineExt as _; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt}; @@ -53,14 +57,48 @@ pub trait NormalizeExt<'tcx> { /// This normalization should be used when the type contains inference variables or the /// projection may be fallible. fn normalize>>(&self, t: T) -> InferOk<'tcx, T>; + + /// Deeply normalizes `value`, replacing all aliases which can by normalized in + /// the current environment. Unlike other normalization routines, this errors + /// in case normalization fails or is ambiguous. + /// + /// In the old solver this simply uses `normalize` and errors in + /// case of ambiguity. The new solver only normalizes in this function and + /// `normalize` is a noop. + /// + /// This only normalize opaque types with `Reveal::All`. + fn deeply_normalize>>( + self, + value: T, + ) -> Result>>; } impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> { fn normalize>>(&self, value: T) -> InferOk<'tcx, T> { - let mut selcx = SelectionContext::new(self.infcx); - let Normalized { value, obligations } = - normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value); - InferOk { value, obligations } + if self.infcx.next_trait_solver() { + InferOk { value, obligations: Vec::new() } + } else { + let mut selcx = SelectionContext::new(self.infcx); + let Normalized { value, obligations } = + normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value); + InferOk { value, obligations } + } + } + + fn deeply_normalize>>( + self, + value: T, + ) -> Result>> { + if self.infcx.next_trait_solver() { + crate::solve::deeply_normalize(self, value) + } else { + let mut fulfill_cx = >::new(&self.infcx); + let value = self + .normalize(value) + .into_value_registering_obligations(self.infcx, &mut *fulfill_cx); + let errors = fulfill_cx.select_all_or_error(self.infcx); + if errors.is_empty() { Ok(value) } else { Err(errors) } + } } } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index edad519cec29e..7fe79fd865ce3 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -30,7 +30,7 @@ pub trait QueryNormalizeExt<'tcx> { /// /// After codegen, when lifetimes do not matter, it is preferable to instead /// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure. - fn query_normalize(&self, value: T) -> Result, NoSolution> + fn query_normalize(self, value: T) -> Result, NoSolution> where T: TypeFoldable>; } @@ -49,7 +49,7 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> { /// normalizing, but for now should be used only when we actually /// know that normalization will succeed, since error reporting /// and other details are still "under development". - fn query_normalize(&self, value: T) -> Result, NoSolution> + fn query_normalize(self, value: T) -> Result, NoSolution> where T: TypeFoldable>, { @@ -60,6 +60,16 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> { self.param_env, self.cause, ); + + if self.infcx.next_trait_solver() { + match crate::solve::deeply_normalize(self, value) { + Ok(value) => return Ok(Normalized { value, obligations: vec![] }), + Err(_errors) => { + return Err(NoSolution); + } + } + } + if !needs_normalization(&value, self.param_env.reveal()) { return Ok(Normalized { value, obligations: vec![] }); } From d2c74491890aed653b27dfd02fcd853603d83527 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 30 Jun 2023 12:15:45 +0200 Subject: [PATCH 05/10] add a `try_structurally_resolve_type` in coerce --- compiler/rustc_hir_typeck/src/coercion.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 35 ++++++++++++------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 5f98bacaf2ad7..9a037f7110e57 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1005,7 +1005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { allow_two_phase: AllowTwoPhase, cause: Option>, ) -> RelateResult<'tcx, Ty<'tcx>> { - let source = self.resolve_vars_with_obligations(expr_ty); + let source = self.try_structurally_resolve_type(expr.span, expr_ty); debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target); let cause = diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index b1c480e0ded4e..d21e78e70cfb5 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1465,16 +1465,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - /// Resolves `typ` by a single level if `typ` is a type variable. + /// Try to resolve `ty` to a structural type, normalizing aliases. /// - /// When the new solver is enabled, this will also attempt to normalize - /// the type if it's a projection (note that it will not deeply normalize - /// projections within the type, just the outermost layer of the type). - /// - /// If no resolution is possible, then an error is reported. - /// Numeric inference variables may be left unresolved. - pub fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { - let mut ty = self.resolve_vars_with_obligations(ty); + /// In case there is still ambiguity, the returned type may be an inference + /// variable. This is different from `structurally_resolve_type` which errors + /// in this case. + pub fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { + let ty = self.resolve_vars_with_obligations(ty); if self.next_trait_solver() && let ty::Alias(ty::Projection, _) = ty.kind() @@ -1483,15 +1480,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .at(&self.misc(sp), self.param_env) .structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut()) { - Ok(normalized_ty) => { - ty = normalized_ty; - }, + Ok(normalized_ty) => normalized_ty, Err(errors) => { let guar = self.err_ctxt().report_fulfillment_errors(&errors); return self.tcx.ty_error(guar); } } - } + } else { + ty + } + } + + /// Resolves `ty` by a single level if `ty` is a type variable. + /// + /// When the new solver is enabled, this will also attempt to normalize + /// the type if it's a projection (note that it will not deeply normalize + /// projections within the type, just the outermost layer of the type). + /// + /// If no resolution is possible, then an error is reported. + /// Numeric inference variables may be left unresolved. + pub fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { + let ty = self.try_structurally_resolve_type(sp, ty); if !ty.is_ty_var() { ty From 5378f07d6419bd1307e32fbba0db0c8b4e443214 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 27 Jun 2023 23:13:39 +0200 Subject: [PATCH 06/10] use `deeply_normalize` for `assumed_wf_types` --- Cargo.lock | 1 + .../rustc_hir_analysis/src/check/check.rs | 17 +++-- .../src/check/compare_impl_item.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 7 +- .../src/impl_wf_check/min_specialization.rs | 22 +++--- compiler/rustc_middle/src/query/mod.rs | 2 +- .../src/traits/coherence.rs | 6 +- .../src/traits/engine.rs | 30 +++++--- compiler/rustc_ty_utils/Cargo.toml | 1 + compiler/rustc_ty_utils/src/implied_bounds.rs | 76 ++++++++++++++----- 10 files changed, 112 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5bc2dc5eefa6a..53a880e5b9f22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4136,6 +4136,7 @@ dependencies = [ name = "rustc_ty_utils" version = "0.0.0" dependencies = [ + "itertools", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 346e153a69d02..d232747b6476a 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -224,7 +224,8 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() { return; } - check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin); + + let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin); } /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result @@ -395,7 +396,7 @@ fn check_opaque_meets_bounds<'tcx>( def_id: LocalDefId, span: Span, origin: &hir::OpaqueTyOrigin, -) { +) -> Result<(), ErrorGuaranteed> { let defining_use_anchor = match *origin { hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did, hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id), @@ -429,10 +430,10 @@ fn check_opaque_meets_bounds<'tcx>( Ok(()) => {} Err(ty_err) => { let ty_err = ty_err.to_string(tcx); - tcx.sess.delay_span_bug( + return Err(tcx.sess.delay_span_bug( span, format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"), - ); + )); } } @@ -447,7 +448,8 @@ fn check_opaque_meets_bounds<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors); + let guar = infcx.err_ctxt().report_fulfillment_errors(&errors); + return Err(guar); } match origin { // Checked when type checking the function containing them. @@ -461,14 +463,15 @@ fn check_opaque_meets_bounds<'tcx>( if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {} // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias { .. } => { - let wf_tys = ocx.assumed_wf_types(param_env, span, def_id); + let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, def_id)?; let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env); + ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?; } } // Clean up after ourselves let _ = infcx.take_opaque_types(); + Ok(()) } fn is_enum_of_nonnullable_ptr<'tcx>( 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 76edeccaf29f5..3f5164e093d73 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2121,7 +2121,7 @@ pub(super) fn check_type_bounds<'tcx>( _ => bug!(), } }; - let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id); + let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl_ty_def_id)?; let normalize_cause = ObligationCause::new( impl_ty_span, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index d34d6f644a73b..506fdccd6c287 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -105,7 +105,12 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( } f(&mut wfcx); - let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id); + let assumed_wf_types = match wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id) + { + Ok(wf_types) => wf_types, + Err(_guar) => return, + }; + let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types); let errors = wfcx.select_all_or_error(); diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 383144ce13960..67800dbd2a2f0 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -77,7 +77,7 @@ use rustc_infer::traits::specialization_graph::Node; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; -use rustc_span::Span; +use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::{self, translate_substs_with_cause, wf, ObligationCtxt}; @@ -113,7 +113,7 @@ fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node let span = tcx.def_span(impl1_def_id); check_has_items(tcx, impl1_def_id, impl2_node, span); - if let Some((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) { + if let Ok((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) { let impl2_def_id = impl2_node.def_id(); debug!(?impl2_def_id, ?impl2_substs); @@ -171,16 +171,14 @@ fn get_impl_substs( tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, -) -> Option<(SubstsRef<'_>, SubstsRef<'_>)> { +) -> Result<(SubstsRef<'_>, SubstsRef<'_>), ErrorGuaranteed> { let infcx = &tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new(infcx); let param_env = tcx.param_env(impl1_def_id); - - let assumed_wf_types = - ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id); + let impl1_span = tcx.def_span(impl1_def_id); + let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?; let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id); - let impl1_span = tcx.def_span(impl1_def_id); let impl2_substs = translate_substs_with_cause( infcx, param_env, @@ -198,8 +196,8 @@ fn get_impl_substs( let errors = ocx.select_all_or_error(); if !errors.is_empty() { - ocx.infcx.err_ctxt().report_fulfillment_errors(&errors); - return None; + let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(&errors); + return Err(guar); } let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types); @@ -207,10 +205,10 @@ fn get_impl_substs( let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env); let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { let span = tcx.def_span(impl1_def_id); - tcx.sess.emit_err(SubstsOnOverriddenImpl { span }); - return None; + let guar = tcx.sess.emit_err(SubstsOnOverriddenImpl { span }); + return Err(guar); }; - Some((impl1_substs, impl2_substs)) + Ok((impl1_substs, impl2_substs)) } /// Returns a list of all of the unconstrained subst of the given impl. diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c12587845e539..a8cdf8286fe71 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -881,7 +881,7 @@ rustc_queries! { /// /// Note that we've liberated the late bound regions of function signatures, so /// this can not be used to check whether these types are well formed. - query assumed_wf_types(key: DefId) -> &'tcx ty::List> { + query assumed_wf_types(key: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 9e1332c1c81dc..4cfe2bfcb12b4 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -427,7 +427,11 @@ fn prove_negated_obligation<'tcx>( let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID); let ocx = ObligationCtxt::new(&infcx); - let wf_tys = ocx.assumed_wf_types(param_env, DUMMY_SP, body_def_id); + let Ok(wf_tys) = ocx.assumed_wf_types(param_env, body_def_id) + else { + return false; + }; + let outlives_env = OutlivesEnvironment::with_bounds( param_env, infcx.implied_bounds_tys(param_env, body_def_id, wf_tys), diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index faa675054b786..2fa69b995ffac 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -4,6 +4,7 @@ use std::fmt::Debug; use super::TraitEngine; use super::{ChalkFulfillmentContext, FulfillmentContext}; use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; +use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::NormalizeExt; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::ErrorGuaranteed; @@ -24,7 +25,6 @@ use rustc_middle::ty::ToPredicate; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::config::TraitSolver; -use rustc_span::Span; pub trait TraitEngineExt<'tcx> { fn new(infcx: &InferCtxt<'tcx>) -> Box; @@ -198,17 +198,24 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { } } + pub fn assumed_wf_types_and_report_errors( + &self, + param_env: ty::ParamEnv<'tcx>, + def_id: LocalDefId, + ) -> Result>, ErrorGuaranteed> { + self.assumed_wf_types(param_env, def_id) + .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(&errors)) + } + pub fn assumed_wf_types( &self, param_env: ty::ParamEnv<'tcx>, - span: Span, def_id: LocalDefId, - ) -> FxIndexSet> { + ) -> Result>, Vec>> { let tcx = self.infcx.tcx; - let assumed_wf_types = tcx.assumed_wf_types(def_id); let mut implied_bounds = FxIndexSet::default(); - let cause = ObligationCause::misc(span, def_id); - for ty in assumed_wf_types { + let mut errors = Vec::new(); + for &(ty, span) in tcx.assumed_wf_types(def_id) { // FIXME(@lcnr): rustc currently does not check wf for types // pre-normalization, meaning that implied bounds are sometimes // incorrect. See #100910 for more details. @@ -221,10 +228,15 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { // sound and then uncomment this line again. // implied_bounds.insert(ty); - let normalized = self.normalize(&cause, param_env, ty); - implied_bounds.insert(normalized); + let cause = ObligationCause::misc(span, def_id); + match self.infcx.at(&cause, param_env).deeply_normalize(ty) { + // Insert well-formed types, ignoring duplicates. + Ok(normalized) => drop(implied_bounds.insert(normalized)), + Err(normalization_errors) => errors.extend(normalization_errors), + }; } - implied_bounds + + if errors.is_empty() { Ok(implied_bounds) } else { Err(errors) } } pub fn make_canonicalized_query_response( diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index 51885c9b47eb8..50dac3a37a4a0 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] tracing = "0.1" +itertools = "0.10.1" rustc_middle = { path = "../rustc_middle" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 081be065864c8..10dec9a7a32be 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -1,45 +1,56 @@ -use rustc_hir::{def::DefKind, def_id::DefId}; +use rustc_hir as hir; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::LocalDefId; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::Span; +use std::iter; pub fn provide(providers: &mut Providers) { *providers = Providers { assumed_wf_types, ..*providers }; } -fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List> { +fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { match tcx.def_kind(def_id) { DefKind::Fn => { let sig = tcx.fn_sig(def_id).subst_identity(); - let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig); - liberated_sig.inputs_and_output + let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); + tcx.arena.alloc_from_iter(itertools::zip_eq( + liberated_sig.inputs_and_output, + fn_sig_spans(tcx, def_id), + )) } DefKind::AssocFn => { let sig = tcx.fn_sig(def_id).subst_identity(); - let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig); + let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); let mut assumed_wf_types: Vec<_> = - tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into(); - assumed_wf_types.extend(liberated_sig.inputs_and_output); - tcx.mk_type_list(&assumed_wf_types) + tcx.assumed_wf_types(tcx.local_parent(def_id)).into(); + assumed_wf_types.extend(itertools::zip_eq( + liberated_sig.inputs_and_output, + fn_sig_spans(tcx, def_id), + )); + tcx.arena.alloc_slice(&assumed_wf_types) } DefKind::Impl { .. } => { - match tcx.impl_trait_ref(def_id) { - Some(trait_ref) => { - let types: Vec<_> = trait_ref.skip_binder().substs.types().collect(); - tcx.mk_type_list(&types) - } - // Only the impl self type - None => tcx.mk_type_list(&[tcx.type_of(def_id).subst_identity()]), - } + // Trait arguments and the self type for trait impls or only the self type for + // inherent impls. + let tys = match tcx.impl_trait_ref(def_id) { + Some(trait_ref) => trait_ref.skip_binder().substs.types().collect(), + None => vec![tcx.type_of(def_id).subst_identity()], + }; + + let mut impl_spans = impl_spans(tcx, def_id); + tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap()))) } - DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)), - DefKind::OpaqueTy => match tcx.def_kind(tcx.parent(def_id)) { + DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), + DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) { DefKind::TyAlias => ty::List::empty(), - DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)), + DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), // Nested opaque types only occur in associated types: // ` type Opaque = impl Trait<&'static T, AssocTy = impl Nested>; ` // assumed_wf_types should include those of `Opaque`, `Opaque` itself // and `&'static T`. - DefKind::OpaqueTy => bug!("unimplemented implied bounds for neseted opaque types"), + DefKind::OpaqueTy => bug!("unimplemented implied bounds for nested opaque types"), def_kind @ _ => { bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}") } @@ -72,3 +83,28 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List> { | DefKind::Generator => ty::List::empty(), } } + +fn fn_sig_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator + '_ { + let node = tcx.hir().get(tcx.local_def_id_to_hir_id(def_id)); + if let Some(decl) = node.fn_decl() { + decl.inputs.iter().map(|ty| ty.span).chain(iter::once(decl.output.span())) + } else { + bug!("unexpected item for fn {def_id:?}: {node:?}") + } +} + +fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator + '_ { + let item = tcx.hir().expect_item(def_id); + if let hir::ItemKind::Impl(impl_) = item.kind { + let trait_args = impl_ + .of_trait + .into_iter() + .flat_map(|trait_ref| trait_ref.path.segments.last().unwrap().args().args) + .map(|arg| arg.span()); + let dummy_spans_for_default_args = + impl_.of_trait.into_iter().flat_map(|trait_ref| iter::repeat(trait_ref.path.span)); + iter::once(impl_.self_ty.span).chain(trait_args).chain(dummy_spans_for_default_args) + } else { + bug!("unexpected item for impl {def_id:?}: {item:?}") + } +} From a2dfed6711353357faf11673f145769f1f232d50 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 29 Jun 2023 14:17:54 +0200 Subject: [PATCH 07/10] `deeply_normalize` pass in fulfill cx for old solver --- .../src/traits/engine.rs | 6 +++++- .../src/traits/project.rs | 21 +++++++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 2fa69b995ffac..19dd4ce06b0b2 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -229,7 +229,11 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { // implied_bounds.insert(ty); let cause = ObligationCause::misc(span, def_id); - match self.infcx.at(&cause, param_env).deeply_normalize(ty) { + match self + .infcx + .at(&cause, param_env) + .deeply_normalize(ty, &mut **self.engine.borrow_mut()) + { // Insert well-formed types, ignoring duplicates. Ok(normalized) => drop(implied_bounds.insert(normalized)), Err(normalization_errors) => errors.extend(normalization_errors), diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e4eea14ef74f7..56724653cb8d8 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -20,7 +20,6 @@ use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use crate::traits::error_reporting::TypeErrCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::select::ProjectionMatchesProjection; -use crate::traits::TraitEngineExt as _; use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorGuaranteed; @@ -32,7 +31,6 @@ use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::FulfillmentError; use rustc_infer::traits::ObligationCauseCode; use rustc_infer::traits::TraitEngine; -use rustc_infer::traits::TraitEngineExt as _; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt}; @@ -59,17 +57,17 @@ pub trait NormalizeExt<'tcx> { fn normalize>>(&self, t: T) -> InferOk<'tcx, T>; /// Deeply normalizes `value`, replacing all aliases which can by normalized in - /// the current environment. Unlike other normalization routines, this errors - /// in case normalization fails or is ambiguous. + /// the current environment. In the new solver this errors in case normalization + /// fails or is ambiguous. This only normalize opaque types with `Reveal::All`. /// - /// In the old solver this simply uses `normalize` and errors in - /// case of ambiguity. The new solver only normalizes in this function and - /// `normalize` is a noop. - /// - /// This only normalize opaque types with `Reveal::All`. + /// In the old solver this simply uses `normalizes` and adds the nested obligations + /// to the `fulfill_cx`. This is necessary as we otherwise end up recomputing the + /// same goals in both a temporary and the shared context which negatively impacts + /// performance as these don't share caching. fn deeply_normalize>>( self, value: T, + fulfill_cx: &mut dyn TraitEngine<'tcx>, ) -> Result>>; } @@ -88,15 +86,16 @@ impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> { fn deeply_normalize>>( self, value: T, + fulfill_cx: &mut dyn TraitEngine<'tcx>, ) -> Result>> { if self.infcx.next_trait_solver() { crate::solve::deeply_normalize(self, value) } else { - let mut fulfill_cx = >::new(&self.infcx); let value = self .normalize(value) .into_value_registering_obligations(self.infcx, &mut *fulfill_cx); - let errors = fulfill_cx.select_all_or_error(self.infcx); + let errors = fulfill_cx.select_where_possible(self.infcx); + let value = self.infcx.resolve_vars_if_possible(value); if errors.is_empty() { Ok(value) } else { Err(errors) } } } From 412c6e0b0737245b029d5a3f7b1189ff7da7c7f0 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 30 Jun 2023 10:57:17 +0200 Subject: [PATCH 08/10] review --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 ++ .../src/solve/normalize.rs | 26 +++++++++---------- .../rustc_trait_selection/src/traits/mod.rs | 7 ++++- .../src/traits/project.rs | 8 +++++- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index d21e78e70cfb5..d9d91b0f6be8f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -83,6 +83,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// version (resolve_vars_if_possible), this version will /// also select obligations if it seems useful, in an effort /// to get more type information. + // FIXME(-Ztrait-solver=next): A lot of the calls to this method should + // probably be `try_structurally_resolve_type` or `structurally_resolve_type` instead. pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> { self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {}) } diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 420a6ee8978ff..1084e7acfeb94 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -1,7 +1,6 @@ use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{needs_normalization, TraitEngineExt as _}; -use crate::traits::{BoundVarReplacer, PlaceholderReplacer}; +use crate::traits::{needs_normalization, BoundVarReplacer, PlaceholderReplacer}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::infer::at::At; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -13,22 +12,23 @@ use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex}; use rustc_middle::ty::{FallibleTypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{TypeFoldable, TypeVisitableExt}; +use super::FulfillmentCtxt; + /// Deeply normalize all aliases in `value`. This does not handle inference and expects /// its input to be already fully resolved. pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable>>( at: At<'_, 'tcx>, value: T, ) -> Result>> { - let mut fulfill_cx = >::new(&at.infcx); - let mut folder = - NormalizationFolder { at, fulfill_cx: &mut *fulfill_cx, depth: 0, universes: Vec::new() }; + let fulfill_cx = FulfillmentCtxt::new(); + let mut folder = NormalizationFolder { at, fulfill_cx, depth: 0, universes: Vec::new() }; value.try_fold_with(&mut folder) } struct NormalizationFolder<'me, 'tcx> { at: At<'me, 'tcx>, - fulfill_cx: &'me mut dyn TraitEngine<'tcx>, + fulfill_cx: FulfillmentCtxt<'tcx>, depth: usize, universes: Vec>, } @@ -163,16 +163,14 @@ impl<'tcx> FallibleTypeFolder> for NormalizationFolder<'_, 'tcx> { return Ok(ty); } - let (kind, data) = match *ty.kind() { - ty::Alias(kind, alias_ty) => (kind, alias_ty), - _ => return ty.try_super_fold_with(self), - }; - // We don't normalize opaque types unless we have // `Reveal::All`, even if we're in the defining scope. - if matches!(kind, ty::Opaque) && reveal == Reveal::UserFacing { - return ty.try_super_fold_with(self); - } + let data = match *ty.kind() { + ty::Alias(kind, alias_ty) if kind != ty::Opaque || reveal == Reveal::UserFacing => { + alias_ty + } + _ => return ty.try_super_fold_with(self), + }; if data.has_escaping_bound_vars() { let (data, mapped_regions, mapped_types, mapped_consts) = diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 89aefc0de530d..720998a51e080 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -409,7 +409,12 @@ pub fn normalize_param_env_or_error<'tcx>( ) } -/// Normalize a type and process all resulting obligations, returning any errors +/// Normalize a type and process all resulting obligations, returning any errors. +/// +/// FIXME(-Ztrait-solver=next): This should be replaced by `At::deeply_normalize` +/// which has the same behavior with the new solver. Because using a separate +/// fulfillment context worsens caching in the old solver, `At::deeply_normalize` +/// is still lazy with the old solver as it otherwise negatively impacts perf. #[instrument(skip_all)] pub fn fully_normalize<'tcx, T>( infcx: &InferCtxt<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 56724653cb8d8..162e51d1fd612 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -58,12 +58,18 @@ pub trait NormalizeExt<'tcx> { /// Deeply normalizes `value`, replacing all aliases which can by normalized in /// the current environment. In the new solver this errors in case normalization - /// fails or is ambiguous. This only normalize opaque types with `Reveal::All`. + /// fails or is ambiguous. This only normalizes opaque types with `Reveal::All`. /// /// In the old solver this simply uses `normalizes` and adds the nested obligations /// to the `fulfill_cx`. This is necessary as we otherwise end up recomputing the /// same goals in both a temporary and the shared context which negatively impacts /// performance as these don't share caching. + /// + /// FIXME(-Ztrait-solver=next): This has the same behavior as `traits::fully_normalize` + /// in the new solver, but because of performance reasons, we currently reuse an + /// existing fulfillment context in the old solver. Once we also eagerly prove goals with + /// the old solver or have removed the old solver, remove `traits::fully_normalize` and + /// rename this function to `At::fully_normalize`. fn deeply_normalize>>( self, value: T, From 30ed152330637774354f6450d49bd193a1b59dcf Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 27 Jun 2023 23:13:50 +0200 Subject: [PATCH 09/10] update tests --- .../issue-109789.stderr | 4 +- .../dyn-star/param-env-infer.current.stderr | 18 ---- tests/ui/dyn-star/param-env-infer.next.stderr | 38 ------- .../param-env-region-infer.current.stderr | 9 ++ ...env-infer.rs => param-env-region-infer.rs} | 7 +- tests/ui/for/issue-20605.next.stderr | 51 +++++++++- tests/ui/for/issue-20605.rs | 15 ++- tests/ui/issues/issue-35570.rs | 1 - tests/ui/issues/issue-35570.stderr | 12 +-- ...ions-implied-bounds-projection-gap-hr-1.rs | 1 - ...-implied-bounds-projection-gap-hr-1.stderr | 17 +--- .../traits/new-solver/alias-bound-unsound.rs | 4 +- .../new-solver/alias-bound-unsound.stderr | 30 +----- .../alias_eq_substs_eq_not_intercrate.rs | 19 ++-- .../alias_eq_substs_eq_not_intercrate.stderr | 11 +++ tests/ui/traits/new-solver/async.fail.stderr | 4 +- tests/ui/traits/new-solver/async.rs | 2 +- .../new-solver/dont-remap-tait-substs.rs | 2 +- .../new-solver/dont-remap-tait-substs.stderr | 99 +++++++++++++++++++ .../equating-projection-cyclically.rs | 12 ++- .../equating-projection-cyclically.stderr | 9 +- .../new-solver/lazy-nested-obligations-2.rs | 3 +- .../lazy-nested-obligations-2.stderr | 39 ++++++++ tests/ui/traits/new-solver/object-unsafety.rs | 10 +- .../traits/new-solver/object-unsafety.stderr | 63 +++++++++++- .../recursive-self-normalization-2.rs | 1 + .../recursive-self-normalization-2.stderr | 10 +- .../recursive-self-normalization.rs | 1 + .../recursive-self-normalization.stderr | 10 +- .../new-solver/slice-match-byte-lit.stderr | 4 +- .../new-solver/specialization-transmute.rs | 12 +-- .../specialization-transmute.stderr | 22 ++--- .../specialization-unconstrained.rs | 2 +- .../specialization-unconstrained.stderr | 11 ++- .../type-alias-impl-trait/cross_inference.rs | 4 +- 35 files changed, 366 insertions(+), 191 deletions(-) delete mode 100644 tests/ui/dyn-star/param-env-infer.current.stderr delete mode 100644 tests/ui/dyn-star/param-env-infer.next.stderr create mode 100644 tests/ui/dyn-star/param-env-region-infer.current.stderr rename tests/ui/dyn-star/{param-env-infer.rs => param-env-region-infer.rs} (64%) create mode 100644 tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr create mode 100644 tests/ui/traits/new-solver/dont-remap-tait-substs.stderr create mode 100644 tests/ui/traits/new-solver/lazy-nested-obligations-2.stderr diff --git a/tests/ui/associated-inherent-types/issue-109789.stderr b/tests/ui/associated-inherent-types/issue-109789.stderr index 7af338274a12b..84fc85cd09e48 100644 --- a/tests/ui/associated-inherent-types/issue-109789.stderr +++ b/tests/ui/associated-inherent-types/issue-109789.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types - --> $DIR/issue-109789.rs:18:1 + --> $DIR/issue-109789.rs:18:11 | LL | fn bar(_: Foo fn(&'a ())>::Assoc) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | = note: expected struct `Foo` found struct `Foo fn(&'a ())>` diff --git a/tests/ui/dyn-star/param-env-infer.current.stderr b/tests/ui/dyn-star/param-env-infer.current.stderr deleted file mode 100644 index b3af7be7950c5..0000000000000 --- a/tests/ui/dyn-star/param-env-infer.current.stderr +++ /dev/null @@ -1,18 +0,0 @@ -warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/param-env-infer.rs:5:12 - | -LL | #![feature(dyn_star, pointer_like_trait)] - | ^^^^^^^^ - | - = note: see issue #102425 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0282]: type annotations needed - --> $DIR/param-env-infer.rs:13:10 - | -LL | t as _ - | ^ cannot infer type - -error: aborting due to previous error; 1 warning emitted - -For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/dyn-star/param-env-infer.next.stderr b/tests/ui/dyn-star/param-env-infer.next.stderr deleted file mode 100644 index 408abecc30d44..0000000000000 --- a/tests/ui/dyn-star/param-env-infer.next.stderr +++ /dev/null @@ -1,38 +0,0 @@ -warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/param-env-infer.rs:5:12 - | -LL | #![feature(dyn_star, pointer_like_trait)] - | ^^^^^^^^ - | - = note: see issue #102425 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0391]: cycle detected when computing type of `make_dyn_star::{opaque#0}` - --> $DIR/param-env-infer.rs:11:60 - | -LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires type-checking `make_dyn_star`... - --> $DIR/param-env-infer.rs:11:1 - | -LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires computing layout of `make_dyn_star::{opaque#0}`... - = note: ...which requires normalizing `make_dyn_star::{opaque#0}`... - = note: ...which again requires computing type of `make_dyn_star::{opaque#0}`, completing the cycle -note: cycle used when checking item types in top-level module - --> $DIR/param-env-infer.rs:5:1 - | -LL | / #![feature(dyn_star, pointer_like_trait)] -LL | | -LL | | -LL | | use std::fmt::Debug; -... | -LL | | -LL | | fn main() {} - | |____________^ - -error: aborting due to previous error; 1 warning emitted - -For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/dyn-star/param-env-region-infer.current.stderr b/tests/ui/dyn-star/param-env-region-infer.current.stderr new file mode 100644 index 0000000000000..c606a50c8a9cb --- /dev/null +++ b/tests/ui/dyn-star/param-env-region-infer.current.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/param-env-region-infer.rs:16:10 + | +LL | t as _ + | ^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/dyn-star/param-env-infer.rs b/tests/ui/dyn-star/param-env-region-infer.rs similarity index 64% rename from tests/ui/dyn-star/param-env-infer.rs rename to tests/ui/dyn-star/param-env-region-infer.rs index 1fb16d7685369..9c337e4a89bd3 100644 --- a/tests/ui/dyn-star/param-env-infer.rs +++ b/tests/ui/dyn-star/param-env-region-infer.rs @@ -1,15 +1,18 @@ // revisions: current next //[next] compile-flags: -Ztrait-solver=next +//[next] check-pass // incremental +// checks that we don't ICE if there are region inference variables in the environment +// when computing `PointerLike` builtin candidates. + #![feature(dyn_star, pointer_like_trait)] -//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes +#![allow(incomplete_features)] use std::fmt::Debug; use std::marker::PointerLike; fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a { - //[next]~^ ERROR cycle detected when computing type of `make_dyn_star::{opaque#0}` t as _ //[current]~^ ERROR type annotations needed } diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index a96a53ca93e4a..d55efedfcbeef 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -20,6 +20,53 @@ error: the type ` as IntoIterator>::IntoIter` is LL | for item in *things { *item = 0 } | ^^^^^^^ -error: aborting due to 3 previous errors +error[E0277]: ` as IntoIterator>::IntoIter` is not an iterator + --> $DIR/issue-20605.rs:5:17 + | +LL | for item in *things { *item = 0 } + | ^^^^^^^ ` as IntoIterator>::IntoIter` is not an iterator + | + = help: the trait `Iterator` is not implemented for ` as IntoIterator>::IntoIter` + +error: the type `&mut as IntoIterator>::IntoIter` is not well-formed + --> $DIR/issue-20605.rs:5:17 + | +LL | for item in *things { *item = 0 } + | ^^^^^^^ + +error[E0614]: type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced + --> $DIR/issue-20605.rs:5:27 + | +LL | for item in *things { *item = 0 } + | ^^^^^ + +error[E0277]: the size for values of type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time + --> $DIR/issue-20605.rs:5:9 + | +LL | for item in *things { *item = 0 } + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `< as IntoIterator>::IntoIter as Iterator>::Item` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + +error: the type `Option<< as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed + --> $DIR/issue-20605.rs:5:17 + | +LL | for item in *things { *item = 0 } + | ^^^^^^^ + +error[E0277]: the size for values of type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time + --> $DIR/issue-20605.rs:5:5 + | +LL | for item in *things { *item = 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `< as IntoIterator>::IntoIter as Iterator>::Item` +note: required by a bound in `None` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0614. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/for/issue-20605.rs b/tests/ui/for/issue-20605.rs index 64156b357051b..50d4c3fddb549 100644 --- a/tests/ui/for/issue-20605.rs +++ b/tests/ui/for/issue-20605.rs @@ -3,9 +3,18 @@ fn changer<'a>(mut things: Box>) { for item in *things { *item = 0 } - //~^ ERROR the size for values of type - //[next]~^^ ERROR the type ` as IntoIterator>::IntoIter` is not well-formed - //[next]~| ERROR the trait bound `dyn Iterator: IntoIterator` is not satisfied + //[current]~^ ERROR the size for values of type + //[next]~^^ ERROR the trait bound `dyn Iterator: IntoIterator` is not satisfied + //[next]~| ERROR the size for values of type ` as IntoIterator>::IntoIter` cannot be known at compilation time + //[next]~| ERROR the type ` as IntoIterator>::IntoIter` is not well-formed + //[next]~| ERROR ` as IntoIterator>::IntoIter` is not an iterator + //[next]~| ERROR the type `&mut as IntoIterator>::IntoIter` is not well-formed + //[next]~| ERROR the size for values of type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time + //[next]~| ERROR the type `Option<< as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed + //[next]~| ERROR the size for values of type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time + //[next]~| ERROR type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced + // FIXME(-Ztrait-solver=next): these error messages are horrible and have to be + // improved before we stabilize the new solver. } fn main() {} diff --git a/tests/ui/issues/issue-35570.rs b/tests/ui/issues/issue-35570.rs index a2b0222d4f395..42bdb423f8f5c 100644 --- a/tests/ui/issues/issue-35570.rs +++ b/tests/ui/issues/issue-35570.rs @@ -7,7 +7,6 @@ trait Trait2<'a> { fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { //~^ ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied - //~| ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied let _e: (usize, usize) = unsafe{mem::transmute(param)}; } diff --git a/tests/ui/issues/issue-35570.stderr b/tests/ui/issues/issue-35570.stderr index 3dc33729d8fdb..2697d46bdb2f4 100644 --- a/tests/ui/issues/issue-35570.stderr +++ b/tests/ui/issues/issue-35570.stderr @@ -4,16 +4,6 @@ error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied LL | fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()` -error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied - --> $DIR/issue-35570.rs:8:1 - | -LL | / fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { -LL | | -LL | | -LL | | let _e: (usize, usize) = unsafe{mem::transmute(param)}; -LL | | } - | |_^ the trait `for<'a> Trait2<'a>` is not implemented for `()` - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs index 1106352037a08..429548f119b14 100644 --- a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs @@ -20,7 +20,6 @@ trait Trait2<'a, 'b> { // do not infer that. fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) //~^ ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied - //~| ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied { } diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr index 3fd39810d4453..6844e86653299 100644 --- a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr @@ -9,21 +9,6 @@ help: consider restricting type parameter `T` LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) | ++++++++++++++++++++++++ -error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied - --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1 - | -LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) -LL | | -LL | | -LL | | { -LL | | } - | |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` - | -help: consider restricting type parameter `T` - | -LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) - | ++++++++++++++++++++++++ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.rs b/tests/ui/traits/new-solver/alias-bound-unsound.rs index 6b6a77e2c7ee8..959f1afa04ea3 100644 --- a/tests/ui/traits/new-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/new-solver/alias-bound-unsound.rs @@ -21,9 +21,7 @@ impl Foo for () { fn main() { let x = String::from("hello, world"); drop(<() as Foo>::copy_me(&x)); - //~^ ERROR `<() as Foo>::Item: Copy` is not satisfied - //~| ERROR `<() as Foo>::Item` is not well-formed - //~| ERROR `<() as Foo>::Item` is not well-formed + //~^ ERROR the type `&<() as Foo>::Item` is not well-formed //~| ERROR `<() as Foo>::Item` is not well-formed println!("{x}"); } diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.stderr b/tests/ui/traits/new-solver/alias-bound-unsound.stderr index 89abc608213e6..5800e2c434064 100644 --- a/tests/ui/traits/new-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/new-solver/alias-bound-unsound.stderr @@ -1,29 +1,8 @@ -error[E0277]: the trait bound `<() as Foo>::Item: Copy` is not satisfied - --> $DIR/alias-bound-unsound.rs:23:10 - | -LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `<() as Foo>::Item` - | -note: required by a bound in `Foo::Item` - --> $DIR/alias-bound-unsound.rs:10:30 - | -LL | type Item: Copy - | ---- required by a bound in this associated type -LL | where -LL | ::Item: Copy; - | ^^^^ required by this bound in `Foo::Item` - -error: the type `<() as Foo>::Item` is not well-formed - --> $DIR/alias-bound-unsound.rs:23:10 - | -LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: the type `<() as Foo>::Item` is not well-formed - --> $DIR/alias-bound-unsound.rs:23:5 +error: the type `&<() as Foo>::Item` is not well-formed + --> $DIR/alias-bound-unsound.rs:23:31 | LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^ + | ^^ error: the type `<() as Foo>::Item` is not well-formed --> $DIR/alias-bound-unsound.rs:23:10 @@ -31,6 +10,5 @@ error: the type `<() as Foo>::Item` is not well-formed LL | drop(<() as Foo>::copy_me(&x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs index b036411be838e..204f6e8b0719e 100644 --- a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs +++ b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs @@ -1,22 +1,17 @@ // compile-flags: -Ztrait-solver=next -// check-pass -// (should not pass, should be turned into a coherence-only test) - -// check that a `alias-eq(::Assoc, ::Assoc)` goal fails. - -// FIXME(deferred_projection_equality): add a test that this is true during coherence +// check that a `alias-eq(::Assoc, ::Assoc)` goal fails +// during coherence. We must not incorrectly constrain `?a` and `?b` to be +// equal. trait TraitB { type Assoc; } -fn needs_a() -> T::Assoc { - unimplemented!() -} +trait Overlaps {} -fn bar() { - let _: <_ as TraitB>::Assoc = needs_a::(); -} +impl Overlaps> for ::Assoc {} +impl Overlaps for ::Assoc {} +//~^ ERROR conflicting implementations of trait fn main() {} diff --git a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr new file mode 100644 index 0000000000000..8eda64e4490b4 --- /dev/null +++ b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `Overlaps>` for type `<_ as TraitB>::Assoc` + --> $DIR/alias_eq_substs_eq_not_intercrate.rs:14:1 + | +LL | impl Overlaps> for ::Assoc {} + | --------------------------------------------------------- first implementation here +LL | impl Overlaps for ::Assoc {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as TraitB>::Assoc` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/new-solver/async.fail.stderr b/tests/ui/traits/new-solver/async.fail.stderr index b395c23ae0057..72fa2eb31613d 100644 --- a/tests/ui/traits/new-solver/async.fail.stderr +++ b/tests/ui/traits/new-solver/async.fail.stderr @@ -1,8 +1,8 @@ -error[E0271]: expected `[async block@$DIR/async.rs:12:17: 12:25]` to be a future that resolves to `i32`, but it resolves to `()` +error[E0271]: type mismatch resolving `<[async block@$DIR/async.rs:12:17: 12:25] as Future>::Output == i32` --> $DIR/async.rs:12:17 | LL | needs_async(async {}); - | ----------- ^^^^^^^^ expected `i32`, found `()` + | ----------- ^^^^^^^^ types differ | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/new-solver/async.rs b/tests/ui/traits/new-solver/async.rs index 195cc35cad2ad..155b71eb74991 100644 --- a/tests/ui/traits/new-solver/async.rs +++ b/tests/ui/traits/new-solver/async.rs @@ -10,7 +10,7 @@ fn needs_async(_: impl Future) {} #[cfg(fail)] fn main() { needs_async(async {}); - //[fail]~^ ERROR to be a future that resolves to `i32`, but it resolves to `()` + //[fail]~^ ERROR type mismatch } #[cfg(pass)] diff --git a/tests/ui/traits/new-solver/dont-remap-tait-substs.rs b/tests/ui/traits/new-solver/dont-remap-tait-substs.rs index 028222f4e6dba..08c08e8307628 100644 --- a/tests/ui/traits/new-solver/dont-remap-tait-substs.rs +++ b/tests/ui/traits/new-solver/dont-remap-tait-substs.rs @@ -1,5 +1,5 @@ // compile-flags: -Ztrait-solver=next -// check-pass +// known-bug: #112825 // Makes sure we don't prepopulate the MIR typeck of `define` // with `Foo = T`, but instead, `Foo = B`, so that diff --git a/tests/ui/traits/new-solver/dont-remap-tait-substs.stderr b/tests/ui/traits/new-solver/dont-remap-tait-substs.stderr new file mode 100644 index 0000000000000..769eea7dfd68b --- /dev/null +++ b/tests/ui/traits/new-solver/dont-remap-tait-substs.stderr @@ -0,0 +1,99 @@ +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/dont-remap-tait-substs.rs:10:24 + | +LL | type Foo = impl NeedsSend; + | ^^^^^^^^^^^^^^^^^ + | +note: ...which requires borrow-checking `define`... + --> $DIR/dont-remap-tait-substs.rs:15:1 + | +LL | fn define(a: A, b: B) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/dont-remap-tait-substs.rs:8:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | type Foo = impl NeedsSend; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/dont-remap-tait-substs.rs:10:24 + | +LL | type Foo = impl NeedsSend; + | ^^^^^^^^^^^^^^^^^ + | +note: ...which requires borrow-checking `define`... + --> $DIR/dont-remap-tait-substs.rs:15:1 + | +LL | fn define(a: A, b: B) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/dont-remap-tait-substs.rs:8:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | type Foo = impl NeedsSend; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/dont-remap-tait-substs.rs:10:24 + | +LL | type Foo = impl NeedsSend; + | ^^^^^^^^^^^^^^^^^ + | +note: ...which requires borrow-checking `define`... + --> $DIR/dont-remap-tait-substs.rs:15:1 + | +LL | fn define(a: A, b: B) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/dont-remap-tait-substs.rs:8:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | type Foo = impl NeedsSend; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/dont-remap-tait-substs.rs:10:24 + | +LL | type Foo = impl NeedsSend; + | ^^^^^^^^^^^^^^^^^ + | +note: ...which requires borrow-checking `define`... + --> $DIR/dont-remap-tait-substs.rs:15:1 + | +LL | fn define(a: A, b: B) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/dont-remap-tait-substs.rs:8:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | type Foo = impl NeedsSend; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/traits/new-solver/equating-projection-cyclically.rs b/tests/ui/traits/new-solver/equating-projection-cyclically.rs index 019c6e81c50e9..2668da1b745df 100644 --- a/tests/ui/traits/new-solver/equating-projection-cyclically.rs +++ b/tests/ui/traits/new-solver/equating-projection-cyclically.rs @@ -1,11 +1,10 @@ // compile-flags: -Ztrait-solver=next -// known-bug: unknown trait Test { type Assoc; } -fn transform(x: T) -> T::Assoc { +fn transform(x: Inv) -> Inv { todo!() } @@ -17,8 +16,13 @@ impl Test for String { type Assoc = String; } +struct Inv(Option<*mut T>); + fn main() { - let mut x = Default::default(); + let mut x: Inv<_> = Inv(None); + // This ends up equating `Inv` with `Inv<::Assoc>` + // which fails the occurs check when generalizing `?x`. x = transform(x); - x = 1i32; + //~^ ERROR mismatched types + x = Inv::(None); } diff --git a/tests/ui/traits/new-solver/equating-projection-cyclically.stderr b/tests/ui/traits/new-solver/equating-projection-cyclically.stderr index 57cbc65a17a92..6031d4f08ee9a 100644 --- a/tests/ui/traits/new-solver/equating-projection-cyclically.stderr +++ b/tests/ui/traits/new-solver/equating-projection-cyclically.stderr @@ -1,13 +1,8 @@ error[E0308]: mismatched types - --> $DIR/equating-projection-cyclically.rs:22:19 + --> $DIR/equating-projection-cyclically.rs:25:9 | LL | x = transform(x); - | ^ expected inferred type, found associated type - | - = note: expected type `_` - found associated type `<_ as Test>::Assoc` - = help: consider constraining the associated type `<_ as Test>::Assoc` to `_` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + | ^^^^^^^^^^^^ cyclic type of infinite size error: aborting due to previous error diff --git a/tests/ui/traits/new-solver/lazy-nested-obligations-2.rs b/tests/ui/traits/new-solver/lazy-nested-obligations-2.rs index 32addd829dcfd..fd91d81cdf0d7 100644 --- a/tests/ui/traits/new-solver/lazy-nested-obligations-2.rs +++ b/tests/ui/traits/new-solver/lazy-nested-obligations-2.rs @@ -1,6 +1,5 @@ -// check-pass // compile-flags: -Ztrait-solver=next -// Issue 95863 +// known-bug: #95863 pub trait With { type F; diff --git a/tests/ui/traits/new-solver/lazy-nested-obligations-2.stderr b/tests/ui/traits/new-solver/lazy-nested-obligations-2.stderr new file mode 100644 index 0000000000000..d0a4cd661b386 --- /dev/null +++ b/tests/ui/traits/new-solver/lazy-nested-obligations-2.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> $DIR/lazy-nested-obligations-2.rs:15:23 + | +LL | let _: V = V(f); + | - ^ types differ + | | + | arguments to this struct are incorrect + | + = note: expected associated type `::F` + found fn item `for<'a> fn(&'a str) {f}` + = help: consider constraining the associated type `::F` to `for<'a> fn(&'a str) {f}` or calling a method that returns `::F` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: tuple struct defined here + --> $DIR/lazy-nested-obligations-2.rs:16:16 + | +LL | pub struct V(::F); + | ^ + +error[E0308]: mismatched types + --> $DIR/lazy-nested-obligations-2.rs:21:30 + | +LL | let _: E3 = E3::Var(f); + | ------- ^ types differ + | | + | arguments to this enum variant are incorrect + | + = note: expected associated type `::F` + found fn item `for<'a> fn(&'a str) {f}` + = help: consider constraining the associated type `::F` to `for<'a> fn(&'a str) {f}` or calling a method that returns `::F` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: tuple variant defined here + --> $DIR/lazy-nested-obligations-2.rs:19:9 + | +LL | Var(::F), + | ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/new-solver/object-unsafety.rs b/tests/ui/traits/new-solver/object-unsafety.rs index 7bdd863a762c4..da843c91478bb 100644 --- a/tests/ui/traits/new-solver/object-unsafety.rs +++ b/tests/ui/traits/new-solver/object-unsafety.rs @@ -10,7 +10,15 @@ fn copy(from: &U::From) -> U::From { pub fn copy_any(t: &T) -> T { copy::>(t) - //~^ ERROR the trait bound `dyn Setup: Setup` is not satisfied + //~^ ERROR the type `& as Setup>::From` is not well-formed + //~| ERROR the trait bound `dyn Setup: Setup` is not satisfied + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR the type ` as Setup>::From` is not well-formed + //~| ERROR the size for values of type ` as Setup>::From` cannot be known at compilation time + + // FIXME(-Ztrait-solver=next): These error messages are horrible and some of them + // are even simple fallout from previous error. } fn main() { diff --git a/tests/ui/traits/new-solver/object-unsafety.stderr b/tests/ui/traits/new-solver/object-unsafety.stderr index 198ac623df8a6..bb7c68b8941f0 100644 --- a/tests/ui/traits/new-solver/object-unsafety.stderr +++ b/tests/ui/traits/new-solver/object-unsafety.stderr @@ -14,6 +14,65 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | pub fn copy_any(t: &T) -> T where dyn Setup: Setup { | ++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: the type `& as Setup>::From` is not well-formed + --> $DIR/object-unsafety.rs:12:31 + | +LL | copy::>(t) + | ^ + +error[E0308]: mismatched types + --> $DIR/object-unsafety.rs:12:31 + | +LL | copy::>(t) + | ------------------------- ^ types differ + | | + | arguments to this function are incorrect + | + = note: expected reference `& as Setup>::From` + found reference `&T` +note: function defined here + --> $DIR/object-unsafety.rs:7:4 + | +LL | fn copy(from: &U::From) -> U::From { + | ^^^^ -------------- + +error[E0308]: mismatched types + --> $DIR/object-unsafety.rs:12:5 + | +LL | pub fn copy_any(t: &T) -> T { + | - - expected `T` because of return type + | | + | this type parameter +LL | copy::>(t) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | + = note: expected type parameter `T` + found associated type ` as Setup>::From` + = note: you might be missing a type parameter or trait bound + +error: the type ` as Setup>::From` is not well-formed + --> $DIR/object-unsafety.rs:12:5 + | +LL | copy::>(t) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the size for values of type ` as Setup>::From` cannot be known at compilation time + --> $DIR/object-unsafety.rs:12:5 + | +LL | copy::>(t) + | ^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | doesn't have a size known at compile-time + | this returned value is of type ` as Setup>::From` + | + = help: the trait `Sized` is not implemented for ` as Setup>::From` + = note: the return type of a function must have a statically known size +help: consider further restricting the associated type + | +LL | pub fn copy_any(t: &T) -> T where as Setup>::From: Sized { + | +++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.rs b/tests/ui/traits/new-solver/recursive-self-normalization-2.rs index 8c029f5179d1f..d086db475ac2c 100644 --- a/tests/ui/traits/new-solver/recursive-self-normalization-2.rs +++ b/tests/ui/traits/new-solver/recursive-self-normalization-2.rs @@ -1,3 +1,4 @@ +//~ ERROR overflow // compile-flags: -Ztrait-solver=next trait Foo1 { diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr b/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr index 139b0a4568018..eebaf21d7dfa9 100644 --- a/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr +++ b/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr @@ -1,16 +1,20 @@ error[E0275]: overflow evaluating the requirement `::Assoc1: Bar` - --> $DIR/recursive-self-normalization-2.rs:15:5 + --> $DIR/recursive-self-normalization-2.rs:16:5 | LL | needs_bar::(); | ^^^^^^^^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`) note: required by a bound in `needs_bar` - --> $DIR/recursive-self-normalization-2.rs:12:17 + --> $DIR/recursive-self-normalization-2.rs:13:17 | LL | fn needs_bar() {} | ^^^ required by this bound in `needs_bar` -error: aborting due to previous error +error[E0275]: overflow evaluating the requirement `::Assoc2` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`) + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.rs b/tests/ui/traits/new-solver/recursive-self-normalization.rs index 06d187b5fdf73..d15df7dea73e4 100644 --- a/tests/ui/traits/new-solver/recursive-self-normalization.rs +++ b/tests/ui/traits/new-solver/recursive-self-normalization.rs @@ -1,3 +1,4 @@ +//~ ERROR overflow evaluating the requirement `::Assoc` [E0275] // compile-flags: -Ztrait-solver=next trait Foo { diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.stderr b/tests/ui/traits/new-solver/recursive-self-normalization.stderr index 8e9b9b4b4cec3..6a87fe2f121e4 100644 --- a/tests/ui/traits/new-solver/recursive-self-normalization.stderr +++ b/tests/ui/traits/new-solver/recursive-self-normalization.stderr @@ -1,16 +1,20 @@ error[E0275]: overflow evaluating the requirement `::Assoc: Bar` - --> $DIR/recursive-self-normalization.rs:11:5 + --> $DIR/recursive-self-normalization.rs:12:5 | LL | needs_bar::(); | ^^^^^^^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`) note: required by a bound in `needs_bar` - --> $DIR/recursive-self-normalization.rs:8:17 + --> $DIR/recursive-self-normalization.rs:9:17 | LL | fn needs_bar() {} | ^^^ required by this bound in `needs_bar` -error: aborting due to previous error +error[E0275]: overflow evaluating the requirement `::Assoc` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`) + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/slice-match-byte-lit.stderr b/tests/ui/traits/new-solver/slice-match-byte-lit.stderr index 294e8bc94bed1..cd48a6d184339 100644 --- a/tests/ui/traits/new-solver/slice-match-byte-lit.stderr +++ b/tests/ui/traits/new-solver/slice-match-byte-lit.stderr @@ -1,8 +1,8 @@ -error[E0271]: type mismatch resolving `[u8; 3] <: as SliceIndex<[u8]>>::Output` +error[E0271]: type mismatch resolving `[u8; 3] <: <[u8] as Index>>::Output` --> $DIR/slice-match-byte-lit.rs:6:9 | LL | match &s[0..3] { - | -------- this expression has type `& as SliceIndex<[u8]>>::Output` + | -------- this expression has type `&<[u8] as Index>>::Output` LL | b"uwu" => {} | ^^^^^^ types differ diff --git a/tests/ui/traits/new-solver/specialization-transmute.rs b/tests/ui/traits/new-solver/specialization-transmute.rs index a54701df4ef7e..f6b19e7adf512 100644 --- a/tests/ui/traits/new-solver/specialization-transmute.rs +++ b/tests/ui/traits/new-solver/specialization-transmute.rs @@ -10,12 +10,11 @@ trait Default { } impl Default for T { - default type Id = T; - - fn intu(&self) -> &Self::Id { + default type Id = T; + // This will be fixed by #111994 + fn intu(&self) -> &Self::Id { //~ ERROR type annotations needed self - //~^ ERROR cannot satisfy `T <: ::Id` - } + } } fn transmute, U: Copy>(t: T) -> U { @@ -24,7 +23,6 @@ fn transmute, U: Copy>(t: T) -> U { use std::num::NonZeroU8; fn main() { - let s = transmute::>(0); - //~^ ERROR cannot satisfy `::Id == Option + let s = transmute::>(0); // this call should then error assert_eq!(s, None); } diff --git a/tests/ui/traits/new-solver/specialization-transmute.stderr b/tests/ui/traits/new-solver/specialization-transmute.stderr index e67c56afc0d0c..09b1405fefbf3 100644 --- a/tests/ui/traits/new-solver/specialization-transmute.stderr +++ b/tests/ui/traits/new-solver/specialization-transmute.stderr @@ -8,24 +8,14 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default -error[E0284]: type annotations needed: cannot satisfy `T <: ::Id` - --> $DIR/specialization-transmute.rs:16:9 +error[E0284]: type annotations needed + --> $DIR/specialization-transmute.rs:15:23 | -LL | self - | ^^^^ cannot satisfy `T <: ::Id` - -error[E0284]: type annotations needed: cannot satisfy `::Id == Option` - --> $DIR/specialization-transmute.rs:27:13 - | -LL | let s = transmute::>(0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `::Id == Option` - | -note: required by a bound in `transmute` - --> $DIR/specialization-transmute.rs:21:25 +LL | fn intu(&self) -> &Self::Id { + | ^^^^^^^^^ cannot infer type | -LL | fn transmute, U: Copy>(t: T) -> U { - | ^^^^^^ required by this bound in `transmute` + = note: cannot satisfy `::Id == _` -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.rs b/tests/ui/traits/new-solver/specialization-unconstrained.rs index 02150689ee5c3..7fd753109be2d 100644 --- a/tests/ui/traits/new-solver/specialization-unconstrained.rs +++ b/tests/ui/traits/new-solver/specialization-unconstrained.rs @@ -11,7 +11,7 @@ trait Default { } impl Default for T { - default type Id = T; + default type Id = T; //~ ERROR type annotations needed } fn test, U>() {} diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.stderr b/tests/ui/traits/new-solver/specialization-unconstrained.stderr index 910925cbaeb0d..9915da1a27a6a 100644 --- a/tests/ui/traits/new-solver/specialization-unconstrained.stderr +++ b/tests/ui/traits/new-solver/specialization-unconstrained.stderr @@ -8,6 +8,12 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default +error[E0282]: type annotations needed + --> $DIR/specialization-unconstrained.rs:14:22 + | +LL | default type Id = T; + | ^ cannot infer type for associated type `::Id` + error[E0284]: type annotations needed: cannot satisfy `::Id == ()` --> $DIR/specialization-unconstrained.rs:20:5 | @@ -20,6 +26,7 @@ note: required by a bound in `test` LL | fn test, U>() {} | ^^^^^^ required by this bound in `test` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0284`. +Some errors have detailed explanations: E0282, E0284. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/type-alias-impl-trait/cross_inference.rs b/tests/ui/type-alias-impl-trait/cross_inference.rs index 07f3dd1997bed..5eaf0ddda994a 100644 --- a/tests/ui/type-alias-impl-trait/cross_inference.rs +++ b/tests/ui/type-alias-impl-trait/cross_inference.rs @@ -5,8 +5,8 @@ #![feature(type_alias_impl_trait)] fn main() { - type T = impl Copy; - let foo: T = (1u32, 2u32); + type Tait = impl Copy; + let foo: Tait = (1u32, 2u32); let x: (_, _) = foo; println!("{:?}", x); } From be6a344365337afced33fcfd86773367aa8fbf98 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 3 Jul 2023 09:24:02 +0200 Subject: [PATCH 10/10] rebase --- compiler/rustc_trait_selection/src/solve/fulfill.rs | 2 +- compiler/rustc_trait_selection/src/solve/normalize.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index d883e48771657..88ee14c4db587 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -41,7 +41,7 @@ impl<'tcx> FulfillmentCtxt<'tcx> { } impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { - #[instrument(level = "debug", skip(self, _infcx))] + #[instrument(level = "debug", skip(self, infcx))] fn register_predicate_obligation( &mut self, infcx: &InferCtxt<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 1084e7acfeb94..d2eed10950f1c 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -20,7 +20,7 @@ pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable>>( at: At<'_, 'tcx>, value: T, ) -> Result>> { - let fulfill_cx = FulfillmentCtxt::new(); + let fulfill_cx = FulfillmentCtxt::new(at.infcx); let mut folder = NormalizationFolder { at, fulfill_cx, depth: 0, universes: Vec::new() }; value.try_fold_with(&mut folder)