From b42604c2b50625626d13277cd162261b8cd42a85 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Mar 2025 18:46:46 +0000 Subject: [PATCH] Fix PostBorrowckAnalysis for old solver --- .../rustc_hir_analysis/src/check/check.rs | 170 ++++++------------ .../traits/fulfillment_errors.rs | 6 +- .../src/traits/normalize.rs | 79 +++++--- .../src/traits/query/normalize.rs | 79 ++++---- .../failed-to-resolve-instance-ice-123145.rs | 3 +- ...iled-to-resolve-instance-ice-123145.stderr | 20 ++- tests/ui/impl-trait/stranded-opaque.rs | 1 + tests/ui/impl-trait/stranded-opaque.stderr | 18 +- .../const_generic_type.infer.stderr | 18 +- .../const_generic_type.rs | 3 +- 10 files changed, 211 insertions(+), 186 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 07b5837bd871d..d85625971b6f5 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -17,11 +17,10 @@ use rustc_lint_defs::builtin::{ use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; -use rustc_middle::ty::error::TypeErrorToStringExt; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{ - AdtDef, BottomUpFolder, GenericArgKind, RegionKind, TypeFoldable, TypeSuperVisitable, + AdtDef, GenericArgKind, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, fold_regions, }; use rustc_session::lint::builtin::UNINHABITED_STATIC; @@ -30,7 +29,6 @@ use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplem use rustc_trait_selection::traits; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use tracing::{debug, instrument}; -use ty::TypingMode; use {rustc_attr_parsing as attr, rustc_hir as hir}; use super::compare_impl_item::check_type_bounds; @@ -254,14 +252,18 @@ fn check_opaque_meets_bounds<'tcx>( | hir::OpaqueTyOrigin::AsyncFn { parent, .. } | hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent, }; + + let misc_cause = ObligationCause::misc(span, def_id); + + // FIXME: We should reveal the TAITs that end up in where clauses here, otherwise we + // will not be able to match param-env candidates in the old solver, since we don't + // have eq-modulo-normalization. This is less of a problem than it seems, since this + // only matters if we have TAITs in where clauses, which isn't achievable with RPIT + // anyways. let param_env = tcx.param_env(defining_use_anchor); - // FIXME(#132279): Once `PostBorrowckAnalysis` is supported in the old solver, this branch should be removed. - let infcx = tcx.infer_ctxt().build(if tcx.next_trait_solver_globally() { - TypingMode::post_borrowck_analysis(tcx, defining_use_anchor) - } else { - TypingMode::analysis_in_body(tcx, defining_use_anchor) - }); + let infcx = + tcx.infer_ctxt().build(TypingMode::post_borrowck_analysis(tcx, defining_use_anchor)); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let args = match origin { @@ -275,33 +277,25 @@ fn check_opaque_meets_bounds<'tcx>( }), }; - let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); - // `ReErased` regions appear in the "parent_args" of closures/coroutines. // We're ignoring them here and replacing them with fresh region variables. // See tests in ui/type-alias-impl-trait/closure_{parent_args,wf_outlives}.rs. // // FIXME: Consider wrapping the hidden type in an existential `Binder` and instantiating it // here rather than using ReErased. + let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); let hidden_ty = tcx.type_of(def_id.to_def_id()).instantiate(tcx, args); let hidden_ty = fold_regions(tcx, hidden_ty, |re, _dbi| match re.kind() { ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)), _ => re, }); - // HACK: We eagerly instantiate some bounds to report better errors for them... - // This isn't necessary for correctness, since we register these bounds when - // equating the opaque below, but we should clean this up in the new solver. + // NOTE: We elaborate the explicit item bounds for better spans. for (predicate, pred_span) in tcx.explicit_item_bounds(def_id).iter_instantiated_copied(tcx, args) { - let predicate = predicate.fold_with(&mut BottomUpFolder { - tcx, - ty_op: |ty| if ty == opaque_ty { hidden_ty } else { ty }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }); - + let predicate = predicate.fold_with(&mut ReplaceOpaques { tcx, opaque_ty, hidden_ty }); + let predicate = ocx.normalize(&misc_cause, param_env, predicate); ocx.register_obligation(Obligation::new( tcx, ObligationCause::new( @@ -314,24 +308,24 @@ fn check_opaque_meets_bounds<'tcx>( )); } - let misc_cause = ObligationCause::misc(span, def_id); - // FIXME: We should just register the item bounds here, rather than equating. - // FIXME(const_trait_impl): When we do that, please make sure to also register - // the `~const` bounds. - match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) { - Ok(()) => {} - Err(ty_err) => { - // Some types may be left "stranded" if they can't be reached - // from a lowered rustc_middle bound but they're mentioned in the HIR. - // This will happen, e.g., when a nested opaque is inside of a non- - // existent associated type, like `impl Trait`. - // See . - let ty_err = ty_err.to_string(tcx); - let guar = tcx.dcx().span_delayed_bug( - span, - format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"), + // And check the `~const` bounds for an RPIT. + if tcx.is_conditionally_const(def_id) { + for (predicate, pred_span) in tcx.const_conditions(def_id).instantiate(tcx, args) { + let predicate = ocx.normalize( + &misc_cause, + param_env, + predicate.to_host_effect_clause(tcx, ty::BoundConstness::Maybe), ); - return Err(guar); + ocx.register_obligation(Obligation::new( + tcx, + ObligationCause::new( + span, + def_id, + ObligationCauseCode::OpaqueTypeBound(pred_span, definition_def_id), + ), + param_env, + predicate, + )); } } @@ -353,26 +347,28 @@ fn check_opaque_meets_bounds<'tcx>( let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, defining_use_anchor)?; ocx.resolve_regions_and_report_errors(defining_use_anchor, param_env, wf_tys)?; - if infcx.next_trait_solver() { - Ok(()) - } else if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } = - origin - { - // HACK: this should also fall through to the hidden type check below, but the original - // implementation had a bug where equivalent lifetimes are not identical. This caused us - // to reject existing stable code that is otherwise completely fine. The real fix is to - // compare the hidden types via our type equivalence/relation infra instead of doing an - // identity check. - let _ = infcx.take_opaque_types(); - Ok(()) - } else { - // Check that any hidden types found during wf checking match the hidden types that `type_of` sees. - for (mut key, mut ty) in infcx.take_opaque_types() { - ty.ty = infcx.resolve_vars_if_possible(ty.ty); - key = infcx.resolve_vars_if_possible(key); - sanity_check_found_hidden_type(tcx, key, ty)?; + Ok(()) +} + +struct ReplaceOpaques<'tcx> { + tcx: TyCtxt<'tcx>, + opaque_ty: Ty<'tcx>, + hidden_ty: Ty<'tcx>, +} + +impl<'tcx> TypeFolder> for ReplaceOpaques<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if ty == self.opaque_ty { + self.hidden_ty + } else if ty.has_opaque_types() { + ty.super_fold_with(self) + } else { + ty } - Ok(()) } } @@ -461,50 +457,6 @@ fn best_definition_site_of_opaque<'tcx>( } } -fn sanity_check_found_hidden_type<'tcx>( - tcx: TyCtxt<'tcx>, - key: ty::OpaqueTypeKey<'tcx>, - mut ty: ty::OpaqueHiddenType<'tcx>, -) -> Result<(), ErrorGuaranteed> { - if ty.ty.is_ty_var() { - // Nothing was actually constrained. - return Ok(()); - } - if let ty::Alias(ty::Opaque, alias) = ty.ty.kind() { - if alias.def_id == key.def_id.to_def_id() && alias.args == key.args { - // Nothing was actually constrained, this is an opaque usage that was - // only discovered to be opaque after inference vars resolved. - return Ok(()); - } - } - let strip_vars = |ty: Ty<'tcx>| { - ty.fold_with(&mut BottomUpFolder { - tcx, - ty_op: |t| t, - ct_op: |c| c, - lt_op: |l| match l.kind() { - RegionKind::ReVar(_) => tcx.lifetimes.re_erased, - _ => l, - }, - }) - }; - // Closures frequently end up containing erased lifetimes in their final representation. - // These correspond to lifetime variables that never got resolved, so we patch this up here. - ty.ty = strip_vars(ty.ty); - // Get the hidden type. - let hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args); - let hidden_ty = strip_vars(hidden_ty); - - // If the hidden types differ, emit a type mismatch diagnostic. - if hidden_ty == ty.ty { - Ok(()) - } else { - let span = tcx.def_span(key.def_id); - let other = ty::OpaqueHiddenType { ty: hidden_ty, span }; - Err(ty.build_mismatch_error(&other, tcx)?.emit()) - } -} - /// Check that the opaque's precise captures list is valid (if present). /// We check this for regular `impl Trait`s and also RPITITs, even though the latter /// are technically GATs. @@ -1801,11 +1753,7 @@ pub(super) fn check_coroutine_obligations( debug!(?typeck_results.coroutine_stalled_predicates); - let mode = if tcx.next_trait_solver_globally() { - TypingMode::post_borrowck_analysis(tcx, def_id) - } else { - TypingMode::analysis_in_body(tcx, def_id) - }; + let mode = TypingMode::post_borrowck_analysis(tcx, def_id); let infcx = tcx .infer_ctxt() @@ -1825,15 +1773,5 @@ pub(super) fn check_coroutine_obligations( return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); } - if !tcx.next_trait_solver_globally() { - // Check that any hidden types found when checking these stalled coroutine obligations - // are valid. - for (key, ty) in infcx.take_opaque_types() { - let hidden_type = infcx.resolve_vars_if_possible(ty); - let key = infcx.resolve_vars_if_possible(key); - sanity_check_found_hidden_type(tcx, key, hidden_type)?; - } - } - Ok(()) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 07a67cde3be1c..0dec3eb0bc82c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -711,7 +711,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Already reported. Overflow(OverflowError::Error(guar)) => { self.set_tainted_by_errors(guar); - return guar + return guar; }, Overflow(_) => { @@ -719,6 +719,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty } => { + if let Err(guar) = expected_ty.error_reported() { + return guar; + } + let mut diag = self.dcx().struct_span_err( span, format!("the constant `{ct}` is not of type `{expected_ty}`"), diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index ad62b456ad461..bfa7bd0ac9ecd 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -2,7 +2,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::infer::at::At; -use rustc_infer::infer::{InferCtxt, InferOk}; +use rustc_infer::infer::{InferCtxt, InferOk, RegionVariableOrigin}; use rustc_infer::traits::{ FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine, }; @@ -11,7 +11,7 @@ use rustc_middle::span_bug; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, - TypingMode, + TypingMode, fold_regions, }; use tracing::{debug, instrument}; @@ -127,11 +127,10 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable>>( // Opaques are treated as rigid outside of `TypingMode::PostAnalysis`, // so we can ignore those. match infcx.typing_mode() { - // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis - TypingMode::Coherence - | TypingMode::Analysis { .. } - | TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE), - TypingMode::PostAnalysis => {} + TypingMode::Coherence | TypingMode::Analysis { .. } => { + flags.remove(ty::TypeFlags::HAS_TY_OPAQUE) + } + TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => {} } value.has_type_flags(flags) @@ -169,6 +168,39 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { if !needs_normalization(self.selcx.infcx, &value) { value } else { value.fold_with(self) } } + + fn normalize_opaque_ty(&mut self, ty: Ty<'tcx>, data: ty::AliasTy<'tcx>) -> Ty<'tcx> { + let recursion_limit = self.cx().recursion_limit(); + if !recursion_limit.value_within_limit(self.depth) { + self.selcx.infcx.err_ctxt().report_overflow_error( + OverflowCause::DeeplyNormalize(data.into()), + self.cause.span, + true, + |_| {}, + ); + } + + let args = data.args.fold_with(self); + let generic_ty = self.cx().type_of(data.def_id); + let mut concrete_ty = generic_ty.instantiate(self.cx(), args); + + if concrete_ty == ty { + concrete_ty = + Ty::new_error_with_message(self.cx(), self.cause.span, "recursive opaque type"); + } + + let concrete_ty = fold_regions(self.cx(), concrete_ty, |re, _dbi| match re.kind() { + ty::ReErased => self.selcx.infcx.next_region_var_in_universe( + RegionVariableOrigin::MiscVariable(self.cause.span), + ty::UniverseIndex::ROOT, + ), + _ => re, + }); + self.depth += 1; + let folded_ty = self.fold_ty(concrete_ty); + self.depth -= 1; + folded_ty + } } impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx> { @@ -223,29 +255,20 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx ty::Opaque => { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.selcx.infcx.typing_mode() { - // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis - TypingMode::Coherence - | TypingMode::Analysis { .. } - | TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self), - TypingMode::PostAnalysis => { - let recursion_limit = self.cx().recursion_limit(); - if !recursion_limit.value_within_limit(self.depth) { - self.selcx.infcx.err_ctxt().report_overflow_error( - OverflowCause::DeeplyNormalize(data.into()), - self.cause.span, - true, - |_| {}, - ); + TypingMode::Coherence | TypingMode::Analysis { .. } => ty.super_fold_with(self), + TypingMode::PostBorrowckAnalysis { defined_opaque_types } => { + if data + .def_id + .as_local() + .is_some_and(|def_id| defined_opaque_types.contains(&def_id)) + { + self.normalize_opaque_ty(ty, data) + } else { + // Treat non-defining opaques as rigid + ty.super_fold_with(self) } - - let args = data.args.fold_with(self); - let generic_ty = self.cx().type_of(data.def_id); - let concrete_ty = generic_ty.instantiate(self.cx(), args); - self.depth += 1; - let folded_ty = self.fold_ty(concrete_ty); - self.depth -= 1; - folded_ty } + TypingMode::PostAnalysis => self.normalize_opaque_ty(ty, data), } } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 165c63f3745a2..51cb6b492d6f2 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -214,41 +214,24 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { ty::Opaque => { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.infcx.typing_mode() { - TypingMode::Coherence - | TypingMode::Analysis { .. } - | TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?, - - TypingMode::PostAnalysis => { - let args = data.args.try_fold_with(self)?; - let recursion_limit = self.cx().recursion_limit(); - - if !recursion_limit.value_within_limit(self.anon_depth) { - let guar = self - .infcx - .err_ctxt() - .build_overflow_error( - OverflowCause::DeeplyNormalize(data.into()), - self.cause.span, - true, - ) - .delay_as_bug(); - return Ok(Ty::new_error(self.cx(), guar)); - } + TypingMode::Coherence | TypingMode::Analysis { .. } => { + ty.try_super_fold_with(self)? + } - let generic_ty = self.cx().type_of(data.def_id); - let mut concrete_ty = generic_ty.instantiate(self.cx(), args); - self.anon_depth += 1; - if concrete_ty == ty { - concrete_ty = Ty::new_error_with_message( - self.cx(), - DUMMY_SP, - "recursive opaque type", - ); + TypingMode::PostBorrowckAnalysis { defined_opaque_types } => { + if data + .def_id + .as_local() + .is_some_and(|def_id| defined_opaque_types.contains(&def_id)) + { + self.normalize_opaque_ty(ty, data)? + } else { + // Treat non-defining opaques as rigid + ty.try_super_fold_with(self)? } - let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty)); - self.anon_depth -= 1; - folded_ty? } + + TypingMode::PostAnalysis => self.normalize_opaque_ty(ty, data)?, } } @@ -358,3 +341,35 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { } } } + +impl<'a, 'tcx> QueryNormalizer<'a, 'tcx> { + fn normalize_opaque_ty( + &mut self, + ty: Ty<'tcx>, + data: ty::AliasTy<'tcx>, + ) -> Result, NoSolution> { + let args = data.args.try_fold_with(self)?; + let recursion_limit = self.cx().recursion_limit(); + if !recursion_limit.value_within_limit(self.anon_depth) { + let guar = self + .infcx + .err_ctxt() + .build_overflow_error( + OverflowCause::DeeplyNormalize(data.into()), + self.cause.span, + true, + ) + .delay_as_bug(); + return Ok(Ty::new_error(self.cx(), guar)); + } + let generic_ty = self.cx().type_of(data.def_id); + let mut concrete_ty = generic_ty.instantiate(self.cx(), args); + self.anon_depth += 1; + if concrete_ty == ty { + concrete_ty = Ty::new_error_with_message(self.cx(), DUMMY_SP, "recursive opaque type"); + } + let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty)); + self.anon_depth -= 1; + Ok(folded_ty?) + } +} diff --git a/tests/ui/impl-trait/failed-to-resolve-instance-ice-123145.rs b/tests/ui/impl-trait/failed-to-resolve-instance-ice-123145.rs index 977827f3b5587..db308aa285d46 100644 --- a/tests/ui/impl-trait/failed-to-resolve-instance-ice-123145.rs +++ b/tests/ui/impl-trait/failed-to-resolve-instance-ice-123145.rs @@ -1,7 +1,5 @@ // ICE failed to resolve instance for ... // issue: rust-lang/rust#123145 -//@ build-fail -//~^^^ ERROR overflow evaluating the requirement `(fn() -> impl Handler trait Handler { fn handle(&self) {} @@ -13,6 +11,7 @@ impl Handler for (L,) {} fn one() -> impl Handler { (one,) + //~^ ERROR overflow evaluating the requirement `(fn() -> impl Handler } fn main() { diff --git a/tests/ui/impl-trait/failed-to-resolve-instance-ice-123145.stderr b/tests/ui/impl-trait/failed-to-resolve-instance-ice-123145.stderr index f61e8c2f8dfea..ea81c72482d1f 100644 --- a/tests/ui/impl-trait/failed-to-resolve-instance-ice-123145.stderr +++ b/tests/ui/impl-trait/failed-to-resolve-instance-ice-123145.stderr @@ -1,14 +1,28 @@ error[E0275]: overflow evaluating the requirement `(fn() -> impl Handler {one},): Handler` + --> $DIR/failed-to-resolve-instance-ice-123145.rs:13:5 + | +LL | (one,) + | ^^^^^^ | note: required for `fn() -> impl Handler {one}` to implement `Handler` - --> $DIR/failed-to-resolve-instance-ice-123145.rs:10:32 + --> $DIR/failed-to-resolve-instance-ice-123145.rs:8:32 | LL | impl H> Handler for F {} | ------- ^^^^^^^ ^ | | | unsatisfied trait bound introduced here - = note: 2 redundant requirements hidden - = note: required for `fn() -> impl Handler {one}` to implement `Handler` + = note: 1 redundant requirement hidden + = note: required for `(fn() -> impl Handler {one},)` to implement `Handler` +note: required by a bound in an opaque type + --> $DIR/failed-to-resolve-instance-ice-123145.rs:12:18 + | +LL | fn one() -> impl Handler { + | ^^^^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/failed-to-resolve-instance-ice-123145.rs:12:1 + | +LL | fn one() -> impl Handler { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/stranded-opaque.rs b/tests/ui/impl-trait/stranded-opaque.rs index 6ce5cbd3b555a..c5fd9d38c90c8 100644 --- a/tests/ui/impl-trait/stranded-opaque.rs +++ b/tests/ui/impl-trait/stranded-opaque.rs @@ -8,6 +8,7 @@ impl Trait for i32 {} fn produce() -> impl Trait { //~^ ERROR associated type `Assoc` not found for `Trait` //~| ERROR associated type `Assoc` not found for `Trait` + //~| ERROR the trait bound `(): Trait` is not satisfied 16 } diff --git a/tests/ui/impl-trait/stranded-opaque.stderr b/tests/ui/impl-trait/stranded-opaque.stderr index 5bea3e2af6b30..f2fb299d1f15a 100644 --- a/tests/ui/impl-trait/stranded-opaque.stderr +++ b/tests/ui/impl-trait/stranded-opaque.stderr @@ -12,6 +12,20 @@ LL | fn produce() -> impl Trait { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 2 previous errors +error[E0277]: the trait bound `(): Trait` is not satisfied + --> $DIR/stranded-opaque.rs:8:39 + | +LL | fn produce() -> impl Trait { + | ^^^^^^^^^^ the trait `Trait` is not implemented for `()` + | + = help: the trait `Trait` is implemented for `i32` +note: required by a bound in an opaque type + --> $DIR/stranded-opaque.rs:8:44 + | +LL | fn produce() -> impl Trait { + | ^^^^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0220`. +Some errors have detailed explanations: E0220, E0277. +For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr index dc15d530fd7a0..cab630b30a96a 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr +++ b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr @@ -6,5 +6,21 @@ LL | async fn test() { | = note: the only supported types are integers, `bool`, and `char` -error: aborting due to 1 previous error +error: the constant `N` is not of type `u32` + --> $DIR/const_generic_type.rs:8:31 + | +LL | async fn test() { + | _______________________________^ +... | +LL | | let x: u32 = N; +LL | | } + | |_^ expected `u32`, found opaque type + | +note: required by a const generic parameter in `test` + --> $DIR/const_generic_type.rs:8:15 + | +LL | async fn test() { + | ^^^^^^^^^^^^ required by this const generic parameter in `test` + +error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.rs b/tests/ui/type-alias-impl-trait/const_generic_type.rs index 9b38f1449f89b..296c56a689476 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.rs +++ b/tests/ui/type-alias-impl-trait/const_generic_type.rs @@ -7,7 +7,8 @@ type Bar = impl std::fmt::Display; #[define_opaque(Bar)] async fn test() { //~^ ERROR: `Bar` is forbidden as the type of a const generic parameter - //[no_infer]~^^ ERROR item does not constrain + //[infer]~| ERROR: the constant `N` is not of type `u32` + //[no_infer]~| ERROR item does not constrain #[cfg(infer)] let x: u32 = N; }