diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 87cc69757b0..28cd18bbb8e 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,8 +1,8 @@ use crate::check::intrinsicck::InlineAsmCtxt; use crate::errors::LinkageType; -use super::compare_method::check_type_bounds; -use super::compare_method::{compare_impl_method, compare_ty_impl}; +use super::compare_impl_item::check_type_bounds; +use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; use super::*; use rustc_attr as attr; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; @@ -468,7 +468,7 @@ fn check_opaque_meets_bounds<'tcx>( // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => { let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors( + let _ = infcx.check_region_obligations_and_report_errors( defining_use_anchor, &outlives_environment, ); @@ -774,7 +774,7 @@ fn check_impl_items_against_trait<'tcx>( let impl_item_full = tcx.hir().impl_item(impl_item.id); match impl_item_full.kind { hir::ImplItemKind::Const(..) => { - let _ = tcx.compare_assoc_const_impl_item_with_trait_item(( + let _ = tcx.compare_impl_const(( impl_item.id.owner_id.def_id, ty_impl_item.trait_item_def_id.unwrap(), )); @@ -791,7 +791,7 @@ fn check_impl_items_against_trait<'tcx>( } hir::ImplItemKind::Type(impl_ty) => { let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); - compare_ty_impl( + compare_impl_ty( tcx, &ty_impl_item, impl_ty.span, diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs similarity index 97% rename from compiler/rustc_hir_analysis/src/check/compare_method.rs rename to compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index c6bda9b4641..a767338ab85 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -34,7 +34,7 @@ use std::iter; /// - `impl_m_span`: span to use for reporting errors /// - `trait_m`: the method in the trait /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation -pub(crate) fn compare_impl_method<'tcx>( +pub(super) fn compare_impl_method<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, trait_m: &ty::AssocItem, @@ -71,7 +71,7 @@ pub(crate) fn compare_impl_method<'tcx>( return; } - if let Err(_) = compare_predicate_entailment( + if let Err(_) = compare_method_predicate_entailment( tcx, impl_m, impl_m_span, @@ -150,7 +150,7 @@ pub(crate) fn compare_impl_method<'tcx>( /// Finally we register each of these predicates as an obligation and check that /// they hold. #[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))] -fn compare_predicate_entailment<'tcx>( +fn compare_method_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, impl_m_span: Span, @@ -337,7 +337,7 @@ fn compare_predicate_entailment<'tcx>( if !errors.is_empty() { match check_implied_wf { CheckImpliedWfMode::Check => { - return compare_predicate_entailment( + return compare_method_predicate_entailment( tcx, impl_m, impl_m_span, @@ -374,7 +374,7 @@ fn compare_predicate_entailment<'tcx>( // becomes a hard error (i.e. ideally we'd just call `resolve_regions_and_report_errors` match check_implied_wf { CheckImpliedWfMode::Check => { - return compare_predicate_entailment( + return compare_method_predicate_entailment( tcx, impl_m, impl_m_span, @@ -407,7 +407,7 @@ enum CheckImpliedWfMode { /// re-check with `Skip`, and emit a lint if it succeeds. Check, /// Skips checking implied well-formedness of the impl method, but will emit - /// a lint if the `compare_predicate_entailment` succeeded. This means that + /// a lint if the `compare_method_predicate_entailment` succeeded. This means that /// the reason that we had failed earlier during `Check` was due to the impl /// having stronger requirements than the trait. Skip, @@ -441,8 +441,41 @@ fn compare_asyncness<'tcx>( Ok(()) } +/// Given a method def-id in an impl, compare the method signature of the impl +/// against the trait that it's implementing. In doing so, infer the hidden types +/// that this method's signature provides to satisfy each return-position `impl Trait` +/// in the trait signature. +/// +/// The method is also responsible for making sure that the hidden types for each +/// RPITIT actually satisfy the bounds of the `impl Trait`, i.e. that if we infer +/// `impl Trait = Foo`, that `Foo: Trait` holds. +/// +/// For example, given the sample code: +/// +/// ``` +/// #![feature(return_position_impl_trait_in_trait)] +/// +/// use std::ops::Deref; +/// +/// trait Foo { +/// fn bar() -> impl Deref; +/// // ^- RPITIT #1 ^- RPITIT #2 +/// } +/// +/// impl Foo for () { +/// fn bar() -> Box { Box::new(String::new()) } +/// } +/// ``` +/// +/// The hidden types for the RPITITs in `bar` would be inferred to: +/// * `impl Deref` (RPITIT #1) = `Box` +/// * `impl Sized` (RPITIT #2) = `String` +/// +/// The relationship between these two types is straightforward in this case, but +/// may be more tenuously connected via other `impl`s and normalization rules for +/// cases of more complicated nested RPITITs. #[instrument(skip(tcx), level = "debug", ret)] -pub fn collect_trait_impl_trait_tys<'tcx>( +pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, ) -> Result<&'tcx FxHashMap>, ErrorGuaranteed> { @@ -550,13 +583,13 @@ pub fn collect_trait_impl_trait_tys<'tcx>( // Unify the whole function signature. We need to do this to fully infer // the lifetimes of the return type, but do this after unifying just the // return types, since we want to avoid duplicating errors from - // `compare_predicate_entailment`. + // `compare_method_predicate_entailment`. match ocx.eq(&cause, param_env, trait_fty, impl_fty) { Ok(()) => {} Err(terr) => { - // This function gets called during `compare_predicate_entailment` when normalizing a + // This function gets called during `compare_method_predicate_entailment` when normalizing a // signature that contains RPITIT. When the method signatures don't match, we have to - // emit an error now because `compare_predicate_entailment` will not report the error + // emit an error now because `compare_method_predicate_entailment` will not report the error // when normalization fails. let emitted = report_trait_method_mismatch( infcx, @@ -589,7 +622,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( infcx.check_region_obligations_and_report_errors( impl_m.def_id.expect_local(), &outlives_environment, - ); + )?; let mut collected_tys = FxHashMap::default(); for (def_id, (ty, substs)) in collector.types { @@ -1516,8 +1549,8 @@ fn compare_generic_param_kinds<'tcx>( Ok(()) } -/// Use `tcx.compare_assoc_const_impl_item_with_trait_item` instead -pub(crate) fn raw_compare_const_impl( +/// Use `tcx.compare_impl_const` instead +pub(super) fn compare_impl_const_raw( tcx: TyCtxt<'_>, (impl_const_item_def, trait_const_item_def): (LocalDefId, DefId), ) -> Result<(), ErrorGuaranteed> { @@ -1617,13 +1650,13 @@ pub(crate) fn raw_compare_const_impl( return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None)); } - // FIXME return `ErrorReported` if region obligations error? let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment); + infcx.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?; + Ok(()) } -pub(crate) fn compare_ty_impl<'tcx>( +pub(super) fn compare_impl_ty<'tcx>( tcx: TyCtxt<'tcx>, impl_ty: &ty::AssocItem, impl_ty_span: Span, @@ -1645,7 +1678,7 @@ pub(crate) fn compare_ty_impl<'tcx>( })(); } -/// The equivalent of [compare_predicate_entailment], but for associated types +/// The equivalent of [compare_method_predicate_entailment], but for associated types /// instead of associated functions. fn compare_type_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, @@ -1730,7 +1763,7 @@ fn compare_type_predicate_entailment<'tcx>( infcx.check_region_obligations_and_report_errors( impl_ty.def_id.expect_local(), &outlives_environment, - ); + )?; Ok(()) } @@ -1749,7 +1782,7 @@ fn compare_type_predicate_entailment<'tcx>( /// from the impl could be overridden). We also can't normalize generic /// associated types (yet) because they contain bound parameters. #[instrument(level = "debug", skip(tcx))] -pub fn check_type_bounds<'tcx>( +pub(super) fn check_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, trait_ty: &ty::AssocItem, impl_ty: &ty::AssocItem, @@ -1944,7 +1977,7 @@ pub fn check_type_bounds<'tcx>( infcx.check_region_obligations_and_report_errors( impl_ty.def_id.expect_local(), &outlives_environment, - ); + )?; let constraints = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); for (key, value) in constraints { diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index ed2aed293a7..382c3f52945 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -63,7 +63,7 @@ a type parameter). */ mod check; -mod compare_method; +mod compare_impl_item; pub mod dropck; pub mod intrinsic; pub mod intrinsicck; @@ -94,7 +94,7 @@ use std::num::NonZeroU32; use crate::require_c_abi_if_c_variadic; use crate::util::common::indenter; -use self::compare_method::collect_trait_impl_trait_tys; +use self::compare_impl_item::collect_return_position_impl_trait_in_trait_tys; use self::region::region_scope_tree; pub fn provide(providers: &mut Providers) { @@ -103,8 +103,8 @@ pub fn provide(providers: &mut Providers) { adt_destructor, check_mod_item_types, region_scope_tree, - collect_trait_impl_trait_tys, - compare_assoc_const_impl_item_with_trait_item: compare_method::raw_compare_const_impl, + collect_return_position_impl_trait_in_trait_tys, + compare_impl_const: compare_impl_item::compare_impl_const_raw, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4f27068429c..6cb899f5176 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -115,7 +115,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( let outlives_environment = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds); - infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment); + let _ = infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment); } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 2790d91572b..bfedf63da97 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -325,7 +325,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); } } _ => { @@ -565,7 +565,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); CoerceUnsizedInfo { custom_kind: kind } } 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 ac60f085304..1aae9e0bd20 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 @@ -181,7 +181,7 @@ fn get_impl_substs( let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_hir_id, assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds); - infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); + let _ = infcx.check_region_obligations_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 }); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e5823660e3f..7222eb77682 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1836,7 +1836,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // In some (most?) cases cause.body_id points to actual body, but in some cases // it's an actual definition. According to the comments (e.g. in - // rustc_hir_analysis/check/compare_method.rs:compare_predicate_entailment) the latter + // rustc_hir_analysis/check/compare_impl_item.rs:compare_predicate_entailment) the latter // is relied upon by some other code. This might (or might not) need cleanup. let body_owner_def_id = self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index a9ef91db059..b17a465eb38 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1693,7 +1693,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, generic_param_scope: LocalDefId, outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Option { + ) -> Result<(), ErrorGuaranteed> { let errors = self.resolve_regions(outlives_env); if let None = self.tainted_by_errors() { @@ -1705,9 +1705,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.report_region_errors(generic_param_scope, &errors); } - (!errors.is_empty()).then(|| { - self.tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted") - }) + if errors.is_empty() { + Ok(()) + } else { + Err(self + .tcx + .sess + .delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted")) + } } // [Note-Type-error-reporting] diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 47bd1564f08..f71c39dc0d2 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -178,7 +178,7 @@ impl<'tcx> InferCtxt<'tcx> { &self, generic_param_scope: LocalDefId, outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Option { + ) -> Result<(), ErrorGuaranteed> { self.process_registered_region_obligations( outlives_env.region_bound_pairs(), outlives_env.param_env, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 9d0ccfeb168..e167bbf57e6 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -223,7 +223,7 @@ provide! { tcx, def_id, other, cdata, generator_kind => { table } trait_def => { table } deduced_param_attrs => { table } - collect_trait_impl_trait_tys => { + collect_return_position_impl_trait_in_trait_tys => { Ok(cdata .root .tables diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 65beb744cf8..214a5842233 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1197,7 +1197,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.params_in_repr[def_id] <- params_in_repr); } if should_encode_trait_impl_trait_tys(tcx, def_id) - && let Ok(table) = self.tcx.collect_trait_impl_trait_tys(def_id) + && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id) { record!(self.tables.trait_impl_trait_tys[def_id] <- table); } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ab512804330..37db2274f67 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -169,7 +169,7 @@ rustc_queries! { separate_provide_extern } - query collect_trait_impl_trait_tys(key: DefId) + query collect_return_position_impl_trait_in_trait_tys(key: DefId) -> Result<&'tcx FxHashMap>, ErrorGuaranteed> { desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } @@ -2117,7 +2117,7 @@ rustc_queries! { desc { "checking to see if `{}` permits being left zeroed", key.ty } } - query compare_assoc_const_impl_item_with_trait_item( + query compare_impl_const( key: (LocalDefId, DefId) ) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0.to_def_id()) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 6d3b94c1fdb..cc53659f827 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -641,11 +641,11 @@ impl<'tcx> TyCtxt<'tcx> { ty::EarlyBinder(self.type_of(def_id)) } - pub fn bound_trait_impl_trait_tys( + pub fn bound_return_position_impl_trait_in_trait_tys( self, def_id: DefId, ) -> ty::EarlyBinder>, ErrorGuaranteed>> { - ty::EarlyBinder(self.collect_trait_impl_trait_tys(def_id)) + ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id)) } pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder> { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 5276da2e49c..f7614997585 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2284,7 +2284,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( obligation.param_env, cause.clone(), obligation.recursion_depth + 1, - tcx.bound_trait_impl_trait_tys(impl_fn_def_id) + tcx.bound_return_position_impl_trait_in_trait_tys(impl_fn_def_id) .map_bound(|tys| { tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id]) }) diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 2da98d33429..8d46ba320fc 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -194,7 +194,7 @@ fn resolve_associated_item<'tcx>( && trait_item_id != leaf_def.item.def_id && let Some(leaf_def_item) = leaf_def.item.def_id.as_local() { - tcx.compare_assoc_const_impl_item_with_trait_item(( + tcx.compare_impl_const(( leaf_def_item, trait_item_id, ))?; diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs index 01165fcebaf..e45bdcf9213 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.rs +++ b/src/test/ui/generic-associated-types/impl_bounds.rs @@ -15,7 +15,6 @@ impl Foo for Fooy { //~^ ERROR impl has stricter requirements than trait type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; //~^ ERROR impl has stricter requirements than trait - //~| ERROR lifetime bound not satisfied type C = String where Self: Copy; //~^ ERROR the trait bound `T: Copy` is not satisfied fn d() where Self: Copy {} diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 442d4f33690..3acd85c8ac6 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -16,28 +16,8 @@ LL | type B<'a, 'b> where 'a: 'b; LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; | ^^ impl has extra requirement `'b: 'a` -error[E0478]: lifetime bound not satisfied - --> $DIR/impl_bounds.rs:16:22 - | -LL | type B<'a, 'b> where 'a: 'b; - | -------------- definition of `B` from trait -... -LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; - | ^^^^^^^^^^^^^^^ - help: try copying this clause from the trait: `, 'a: 'b` - | -note: lifetime parameter instantiated with the lifetime `'a` as defined here - --> $DIR/impl_bounds.rs:16:12 - | -LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; - | ^^ -note: but lifetime parameter must outlive the lifetime `'b` as defined here - --> $DIR/impl_bounds.rs:16:16 - | -LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; - | ^^ - error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/impl_bounds.rs:19:33 + --> $DIR/impl_bounds.rs:18:33 | LL | type C = String where Self: Copy; | ^^^^ the trait `Copy` is not implemented for `T` @@ -62,7 +42,7 @@ LL | impl Foo for Fooy { | +++++++++++++++++++ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/impl_bounds.rs:21:24 + --> $DIR/impl_bounds.rs:20:24 | LL | fn d() where Self: Copy {} | ^^^^ the trait `Copy` is not implemented for `T` @@ -86,7 +66,7 @@ help: consider restricting type parameter `T` LL | impl Foo for Fooy { | +++++++++++++++++++ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0276, E0277, E0478. +Some errors have detailed explanations: E0276, E0277. For more information about an error, try `rustc --explain E0276`.