diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 62d49a62744e7..148e75aa84cc7 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -3,7 +3,8 @@ use rustc_index::bit_set::DenseBitSet; use rustc_index::interval::IntervalSet; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives::for_liveness; -use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location}; +use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, HasLocalDecls, Local, Location}; +use rustc_middle::span_bug; use rustc_middle::traits::query::DropckOutlivesResult; use rustc_middle::ty::relate::Relate; use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; @@ -11,7 +12,10 @@ use rustc_mir_dataflow::ResultsCursor; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex}; use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; -use rustc_span::DUMMY_SP; +use rustc_span::{DUMMY_SP, Span}; +use rustc_trait_selection::error_reporting::InferCtxtErrorExt; +use rustc_trait_selection::traits::ObligationCtxt; +use rustc_trait_selection::traits::query::dropck_outlives; use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOp, TypeOpOutput}; use tracing::debug; @@ -162,9 +166,10 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { fn dropck_boring_locals(&mut self, boring_locals: Vec) { for local in boring_locals { let local_ty = self.cx.body.local_decls[local].ty; + let local_span = self.cx.body.local_decls[local].source_info.span; let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({ let typeck = &self.cx.typeck; - move || LivenessContext::compute_drop_data(typeck, local_ty) + move || LivenessContext::compute_drop_data(typeck, local_ty, local_span) }); drop_data.dropck_result.report_overflows( @@ -522,9 +527,10 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { values::pretty_print_points(self.location_map, live_at.iter()), ); + let local_span = self.body.local_decls()[dropped_local].source_info.span; let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({ let typeck = &self.typeck; - move || Self::compute_drop_data(typeck, dropped_ty) + move || Self::compute_drop_data(typeck, dropped_ty, local_span) }); if let Some(data) = &drop_data.region_constraint_data { @@ -589,19 +595,44 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { } } - fn compute_drop_data(typeck: &TypeChecker<'_, 'tcx>, dropped_ty: Ty<'tcx>) -> DropData<'tcx> { - debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,); + fn compute_drop_data( + typeck: &TypeChecker<'_, 'tcx>, + dropped_ty: Ty<'tcx>, + span: Span, + ) -> DropData<'tcx> { + debug!("compute_drop_data(dropped_ty={:?})", dropped_ty); + + let op = typeck.infcx.param_env.and(DropckOutlives { dropped_ty }); - match typeck - .infcx - .param_env - .and(DropckOutlives { dropped_ty }) - .fully_perform(typeck.infcx, DUMMY_SP) - { + match op.fully_perform(typeck.infcx, DUMMY_SP) { Ok(TypeOpOutput { output, constraints, .. }) => { DropData { dropck_result: output, region_constraint_data: constraints } } - Err(_) => DropData { dropck_result: Default::default(), region_constraint_data: None }, + Err(_) => { + // We don't run dropck on HIR, and dropck looks inside fields of + // types, so there's no guarantee that it succeeds. We also + // can't rely on the the `ErrorGuaranteed` from `fully_perform` here + // because it comes from delay_span_bug. + let ocx = ObligationCtxt::new_with_diagnostics(&typeck.infcx); + let errors = + match dropck_outlives::compute_dropck_outlives_with_errors(&ocx, op, span) { + Ok(_) => ocx.select_all_or_error(), + Err(e) => { + if e.is_empty() { + ocx.select_all_or_error() + } else { + e + } + } + }; + + if !errors.is_empty() { + typeck.infcx.err_ctxt().report_fulfillment_errors(errors); + } else { + span_bug!(span, "Rerunning drop data query produced no error."); + } + DropData { dropck_result: Default::default(), region_constraint_data: None } + } } } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index cd81890598e73..3b74a513f213c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -802,7 +802,7 @@ rustc_queries! { query adt_dtorck_constraint( key: DefId - ) -> Result<&'tcx DropckConstraint<'tcx>, NoSolution> { + ) -> &'tcx DropckConstraint<'tcx> { desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 2de55e38052e3..48d9382c055a2 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -266,8 +266,21 @@ where let tcx = self.tcx(); assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis); - let field_ty = - tcx.normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args)); + // The type error for normalization may have been in dropck: see + // `compute_drop_data` in rustc_borrowck, in which case we wouldn't have + // deleted the MIR body and could have an error here as well. + let field_ty = match tcx + .try_normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args)) + { + Ok(t) => t, + Err(_) => Ty::new_error( + self.tcx(), + self.elaborator + .body() + .tainted_by_errors + .expect("Error in drop elaboration not found by dropck."), + ), + }; (tcx.mk_place_field(base_place, field, field_ty), subpath) }) diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 92098e204487a..f04a5feba3011 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -2,12 +2,13 @@ use rustc_data_structures::fx::FxHashSet; use rustc_infer::traits::query::type_op::DropckOutlives; use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult}; use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt}; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::Span; use tracing::{debug, instrument}; +use crate::solve::NextSolverError; use crate::traits::query::NoSolution; use crate::traits::query::normalize::QueryNormalizeExt; -use crate::traits::{Normalized, ObligationCause, ObligationCtxt}; +use crate::traits::{FromSolverError, Normalized, ObligationCause, ObligationCtxt}; /// This returns true if the type `ty` is "trivial" for /// dropck-outlives -- that is, if it doesn't require any types to @@ -93,6 +94,20 @@ pub fn compute_dropck_outlives_inner<'tcx>( goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>, span: Span, ) -> Result, NoSolution> { + match compute_dropck_outlives_with_errors(ocx, goal, span) { + Ok(r) => Ok(r), + Err(_) => Err(NoSolution), + } +} + +pub fn compute_dropck_outlives_with_errors<'tcx, E>( + ocx: &ObligationCtxt<'_, 'tcx, E>, + goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>, + span: Span, +) -> Result, Vec> +where + E: FromSolverError<'tcx, NextSolverError<'tcx>>, +{ let tcx = ocx.infcx.tcx; let ParamEnvAnd { param_env, value: DropckOutlives { dropped_ty } } = goal; @@ -149,11 +164,11 @@ pub fn compute_dropck_outlives_inner<'tcx>( dtorck_constraint_for_ty_inner( tcx, ocx.infcx.typing_env(param_env), - DUMMY_SP, + span, depth, ty, &mut constraints, - )?; + ); // "outlives" represent types/regions that may be touched // by a destructor. @@ -173,11 +188,20 @@ pub fn compute_dropck_outlives_inner<'tcx>( // do not themselves define a destructor", more or less. We have // to push them onto the stack to be expanded. for ty in constraints.dtorck_types.drain(..) { - let Normalized { value: ty, obligations } = - ocx.infcx.at(&cause, param_env).query_normalize(ty)?; - ocx.register_obligations(obligations); + let ty = if let Ok(Normalized { value: ty, obligations }) = + ocx.infcx.at(&cause, param_env).query_normalize(ty) + { + ocx.register_obligations(obligations); + + debug!("dropck_outlives: ty from dtorck_types = {:?}", ty); + ty + } else { + ocx.deeply_normalize(&cause, param_env, ty)?; - debug!("dropck_outlives: ty from dtorck_types = {:?}", ty); + let errors = ocx.select_where_possible(); + debug!("normalize errors: {ty} ~> {errors:#?}"); + return Err(errors); + }; match ty.kind() { // All parameters live for the duration of the @@ -213,14 +237,14 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( depth: usize, ty: Ty<'tcx>, constraints: &mut DropckConstraint<'tcx>, -) -> Result<(), NoSolution> { +) { if !tcx.recursion_limit().value_within_limit(depth) { constraints.overflows.push(ty); - return Ok(()); + return; } if trivial_dropck_outlives(tcx, ty) { - return Ok(()); + return; } match ty.kind() { @@ -244,22 +268,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( // single-element containers, behave like their element rustc_data_structures::stack::ensure_sufficient_stack(|| { dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, *ety, constraints) - })?; + }); } ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| { for ty in tys.iter() { - dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?; + dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints); } - Ok::<_, NoSolution>(()) - })?, + }), ty::Closure(_, args) => rustc_data_structures::stack::ensure_sufficient_stack(|| { for ty in args.as_closure().upvar_tys() { - dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?; + dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints); } - Ok::<_, NoSolution>(()) - })?, + }), ty::CoroutineClosure(_, args) => { rustc_data_structures::stack::ensure_sufficient_stack(|| { @@ -271,10 +293,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( depth + 1, ty, constraints, - )?; + ); } - Ok::<_, NoSolution>(()) - })? + }) } ty::Coroutine(_, args) => { @@ -313,7 +334,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( ty::Adt(def, args) => { let DropckConstraint { dtorck_types, outlives, overflows } = - tcx.at(span).adt_dtorck_constraint(def.did())?; + tcx.at(span).adt_dtorck_constraint(def.did()); // FIXME: we can try to recursively `dtorck_constraint_on_ty` // there, but that needs some way to handle cycles. constraints @@ -346,9 +367,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => { // By the time this code runs, all type variables ought to // be fully resolved. - return Err(NoSolution); + tcx.dcx().span_delayed_bug(span, format!("Unresolved type in dropck: {:?}.", ty)); } } - - Ok(()) } diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index b3377e15aa791..5eddad39e2be2 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -30,10 +30,7 @@ fn dropck_outlives<'tcx>( } /// Calculates the dtorck constraint for a type. -pub(crate) fn adt_dtorck_constraint( - tcx: TyCtxt<'_>, - def_id: DefId, -) -> Result<&DropckConstraint<'_>, NoSolution> { +pub(crate) fn adt_dtorck_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &DropckConstraint<'_> { let def = tcx.adt_def(def_id); let span = tcx.def_span(def_id); let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id); @@ -52,20 +49,20 @@ pub(crate) fn adt_dtorck_constraint( overflows: vec![], }; debug!("dtorck_constraint: {:?} => {:?}", def, result); - return Ok(tcx.arena.alloc(result)); + return tcx.arena.alloc(result); } let mut result = DropckConstraint::empty(); for field in def.all_fields() { let fty = tcx.type_of(field.did).instantiate_identity(); - dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result)?; + dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result); } result.outlives.extend(tcx.destructor_constraints(def)); dedup_dtorck_constraint(&mut result); debug!("dtorck_constraint: {:?} => {:?}", def, result); - Ok(tcx.arena.alloc(result)) + tcx.arena.alloc(result) } fn dedup_dtorck_constraint(c: &mut DropckConstraint<'_>) { diff --git a/tests/crashes/103899.rs b/tests/crashes/103899.rs deleted file mode 100644 index 39c2d72bd357c..0000000000000 --- a/tests/crashes/103899.rs +++ /dev/null @@ -1,27 +0,0 @@ -//@ known-bug: #103899 - -trait BaseWithAssoc { - type Assoc; -} - -trait WrapperWithAssoc { - type BaseAssoc: BaseWithAssoc; -} - -struct Wrapper { - inner: B, -} - -struct ProjectToBase { - data_type_h: T::Assoc, -} - -struct DoubleProject { - buffer: Wrapper>, -} - -fn trigger>() -> DoubleProject { - loop {} -} - -fn main() {} diff --git a/tests/crashes/105299.rs b/tests/crashes/105299.rs deleted file mode 100644 index 8e3aafa47bc9f..0000000000000 --- a/tests/crashes/105299.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ known-bug: #105299 - -pub trait Foo: Clone {} - -pub struct Bar<'a, T: Clone> { - pub cow: std::borrow::Cow<'a, [T]>, - - pub THIS_CAUSES_ICE: (), // #1 -} - -impl Bar<'_, T> -where - T: Clone, - [T]: Foo, -{ - pub fn MOVES_SELF(self) {} // #2 -} - -pub fn main() {} diff --git a/tests/ui/dropck/dropck-only-error-ambiguity.rs b/tests/ui/dropck/dropck-only-error-ambiguity.rs new file mode 100644 index 0000000000000..ddba2af707032 --- /dev/null +++ b/tests/ui/dropck/dropck-only-error-ambiguity.rs @@ -0,0 +1,23 @@ +// Test that we don't ICE for a typeck error that only shows up in dropck +// Version where the normalization error is an ambiguous trait implementation. +// <[T] as ToOwned>::Owned is ambiguous on whether to use T: Clone or [T]::Clone. +// Regression test for #105299 + +pub trait Foo: Clone {} + +pub struct Bar<'a, T: Clone> { + pub cow: std::borrow::Cow<'a, [T]>, + + pub THIS_CAUSES_ICE: (), +} + +impl Bar<'_, T> +where + T: Clone, + [T]: Foo, +{ + pub fn MOVES_SELF(self) {} + //~^ ERROR type annotations needed +} + +pub fn main() {} diff --git a/tests/ui/dropck/dropck-only-error-ambiguity.stderr b/tests/ui/dropck/dropck-only-error-ambiguity.stderr new file mode 100644 index 0000000000000..de19bd49f4e9a --- /dev/null +++ b/tests/ui/dropck/dropck-only-error-ambiguity.stderr @@ -0,0 +1,11 @@ +error[E0284]: type annotations needed + --> $DIR/dropck-only-error-ambiguity.rs:19:23 + | +LL | pub fn MOVES_SELF(self) {} + | ^^^^ cannot infer type + | + = note: cannot satisfy `<[T] as ToOwned>::Owned == _` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/crashes/135039.rs b/tests/ui/dropck/dropck-only-error-async.rs similarity index 62% rename from tests/crashes/135039.rs rename to tests/ui/dropck/dropck-only-error-async.rs index c4c5336fd4fdd..71158e3c6ef7a 100644 --- a/tests/crashes/135039.rs +++ b/tests/ui/dropck/dropck-only-error-async.rs @@ -1,7 +1,6 @@ -//@ known-bug: #135039 -//@ edition:2021 - -pub type UserId = <::User as AuthUser>::Id; +// Test that we don't ICE for a typeck error that only shows up in dropck +// issue #135039 +//@ edition:2018 pub trait AuthUser { type Id; @@ -13,7 +12,7 @@ pub trait AuthnBackend { pub struct AuthSession { user: Option, - data: Option>, + data: Option<<::User as AuthUser>::Id>, } pub trait Authz: Sized { @@ -27,8 +26,12 @@ pub trait Query { pub async fn run_query + 'static>( auth: AuthSession, + //~^ ERROR the trait bound `User: AuthUser` is not satisfied [E0277] + //~| ERROR the trait bound `User: AuthUser` is not satisfied [E0277] query: Q, ) -> Result { let user = auth.user; query.run().await } + +fn main() {} diff --git a/tests/ui/dropck/dropck-only-error-async.stderr b/tests/ui/dropck/dropck-only-error-async.stderr new file mode 100644 index 0000000000000..4a069c8ac33a6 --- /dev/null +++ b/tests/ui/dropck/dropck-only-error-async.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `User: AuthUser` is not satisfied + --> $DIR/dropck-only-error-async.rs:28:5 + | +LL | auth: AuthSession, + | ^^^^ the trait `AuthUser` is not implemented for `User` + +error[E0277]: the trait bound `User: AuthUser` is not satisfied + --> $DIR/dropck-only-error-async.rs:28:5 + | +LL | auth: AuthSession, + | ^^^^ the trait `AuthUser` is not implemented for `User` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/crashes/91985.rs b/tests/ui/dropck/dropck-only-error-gat.rs similarity index 70% rename from tests/crashes/91985.rs rename to tests/ui/dropck/dropck-only-error-gat.rs index 338550430e1f8..dadcf76a43f35 100644 --- a/tests/crashes/91985.rs +++ b/tests/ui/dropck/dropck-only-error-gat.rs @@ -1,6 +1,6 @@ -//@ known-bug: #91985 - -#![feature(generic_associated_types)] +// Test that we don't ICE for a typeck error that only shows up in dropck +// Version that uses a generic associated type +// Regression test for #91985 pub trait Trait1 { type Associated: Ord; @@ -22,7 +22,7 @@ impl GatTrait for GatStruct { pub struct OuterStruct { inner: InnerStruct, - t1: T1, + t1: T1, } pub struct InnerStruct { @@ -35,6 +35,7 @@ where T2: Trait2, { pub fn new() -> Self { + //~^ ERROR the trait bound `::Associated: Clone` is not satisfied todo!() } } diff --git a/tests/ui/dropck/dropck-only-error-gat.stderr b/tests/ui/dropck/dropck-only-error-gat.stderr new file mode 100644 index 0000000000000..53982c0826a74 --- /dev/null +++ b/tests/ui/dropck/dropck-only-error-gat.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `::Associated: Clone` is not satisfied + --> $DIR/dropck-only-error-gat.rs:37:21 + | +LL | pub fn new() -> Self { + | ^^^^ the trait `Clone` is not implemented for `::Associated` + | +note: required by a bound in `GatTrait::Gat` + --> $DIR/dropck-only-error-gat.rs:14:17 + | +LL | type Gat; + | ^^^^^ required by this bound in `GatTrait::Gat` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dropck/dropck-only-error.rs b/tests/ui/dropck/dropck-only-error.rs new file mode 100644 index 0000000000000..e85eeb82e00b9 --- /dev/null +++ b/tests/ui/dropck/dropck-only-error.rs @@ -0,0 +1,23 @@ +// Test that we don't ICE for a typeck error that only shows up in dropck +// issue #135039 + +pub trait AuthUser { + type Id; +} + +pub trait AuthnBackend { + type User: AuthUser; +} + +pub struct AuthSession { + data: Option<<::User as AuthUser>::Id>, +} + +pub trait Authz: Sized { + type AuthnBackend: AuthnBackend; +} + +pub fn run_query(auth: AuthSession) {} +//~^ ERROR the trait bound `User: AuthUser` is not satisfied [E0277] + +fn main() {} diff --git a/tests/ui/dropck/dropck-only-error.stderr b/tests/ui/dropck/dropck-only-error.stderr new file mode 100644 index 0000000000000..6c7cd5d296c40 --- /dev/null +++ b/tests/ui/dropck/dropck-only-error.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `User: AuthUser` is not satisfied + --> $DIR/dropck-only-error.rs:20:31 + | +LL | pub fn run_query(auth: AuthSession) {} + | ^^^^ the trait `AuthUser` is not implemented for `User` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-103899.current.stderr b/tests/ui/typeck/issue-103899.current.stderr new file mode 100644 index 0000000000000..a3a164907be48 --- /dev/null +++ b/tests/ui/typeck/issue-103899.current.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): BaseWithAssoc` is not satisfied + --> $DIR/issue-103899.rs:24:54 + | +LL | fn trigger>() -> DoubleProject { + | ^^^^^^^^^^^^^^^^ the trait `BaseWithAssoc` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/issue-103899.rs:4:1 + | +LL | trait BaseWithAssoc { + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-103899.next.stderr b/tests/ui/typeck/issue-103899.next.stderr new file mode 100644 index 0000000000000..a3a164907be48 --- /dev/null +++ b/tests/ui/typeck/issue-103899.next.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): BaseWithAssoc` is not satisfied + --> $DIR/issue-103899.rs:24:54 + | +LL | fn trigger>() -> DoubleProject { + | ^^^^^^^^^^^^^^^^ the trait `BaseWithAssoc` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/issue-103899.rs:4:1 + | +LL | trait BaseWithAssoc { + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-103899.rs b/tests/ui/typeck/issue-103899.rs index 81ab92a8994c4..92356ecf288b1 100644 --- a/tests/ui/typeck/issue-103899.rs +++ b/tests/ui/typeck/issue-103899.rs @@ -1,9 +1,5 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) -//@ check-fail -//@ failure-status: 101 -//@ dont-check-compiler-stderr -//@ known-bug: #103899 trait BaseWithAssoc { type Assoc; @@ -26,6 +22,7 @@ struct DoubleProject { } fn trigger>() -> DoubleProject { + //~^ ERROR the trait bound `(): BaseWithAssoc` is not satisfied [E0277] loop {} } diff --git a/tests/ui/wf/hir-wf-check-erase-regions.rs b/tests/ui/wf/hir-wf-check-erase-regions.rs index 01893044c278d..20cc1cfe73018 100644 --- a/tests/ui/wf/hir-wf-check-erase-regions.rs +++ b/tests/ui/wf/hir-wf-check-erase-regions.rs @@ -8,7 +8,9 @@ impl<'a, T, const N: usize> IntoIterator for &'a Table { //~^ ERROR `&'a T` is not an iterator type Item = &'a T; - fn into_iter(self) -> Self::IntoIter { //~ ERROR `&'a T` is not an iterator + fn into_iter(self) -> Self::IntoIter { + //~^ ERROR `&'a T` is not an iterator + //~| ERROR `&T` is not an iterator unimplemented!() } } diff --git a/tests/ui/wf/hir-wf-check-erase-regions.stderr b/tests/ui/wf/hir-wf-check-erase-regions.stderr index 4b696dc1d1dfe..e4d48bf82c000 100644 --- a/tests/ui/wf/hir-wf-check-erase-regions.stderr +++ b/tests/ui/wf/hir-wf-check-erase-regions.stderr @@ -34,6 +34,16 @@ LL | fn into_iter(self) -> Self::IntoIter { note: required by a bound in `Flatten` --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL -error: aborting due to 3 previous errors +error[E0277]: `&T` is not an iterator + --> $DIR/hir-wf-check-erase-regions.rs:11:27 + | +LL | fn into_iter(self) -> Self::IntoIter { + | ^^^^^^^^^^^^^^ `&T` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&T` + = help: the trait `Iterator` is implemented for `&mut I` + = note: required for `&T` to implement `IntoIterator` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`.