diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 94e7376ddb216..3154859bc651b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -26,6 +26,7 @@ use rustc_middle::mir::interpret; use rustc_middle::thir; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::TyEncoder; +use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_serialize::{opaque, Encodable, Encoder}; use rustc_session::config::CrateType; @@ -2033,15 +2034,19 @@ impl EncodeContext<'a, 'tcx> { struct ImplVisitor<'tcx> { tcx: TyCtxt<'tcx>, - impls: FxHashMap)>>, + impls: FxHashMap)>>, } impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { if let hir::ItemKind::Impl { .. } = item.kind { if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) { - let simplified_self_ty = - ty::fast_reject::simplify_type(self.tcx, trait_ref.self_ty(), false); + let simplified_self_ty = fast_reject::simplify_type( + self.tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ); self.impls .entry(trait_ref.def_id) diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 11ee942b83e77..c4043d9698cc1 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -1,3 +1,4 @@ +use crate::mir::Mutability; use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::DefId; @@ -27,9 +28,12 @@ where UintSimplifiedType(ty::UintTy), FloatSimplifiedType(ty::FloatTy), AdtSimplifiedType(D), + ForeignSimplifiedType(D), StrSimplifiedType, ArraySimplifiedType, - PtrSimplifiedType, + SliceSimplifiedType, + RefSimplifiedType(Mutability), + PtrSimplifiedType(Mutability), NeverSimplifiedType, TupleSimplifiedType(usize), /// A trait object, all of whose components are markers @@ -42,22 +46,48 @@ where OpaqueSimplifiedType(D), FunctionSimplifiedType(usize), ParameterSimplifiedType, - ForeignSimplifiedType(DefId), } -/// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc. -/// The idea is to get something simple that we can use to quickly decide if two types could unify -/// during method lookup. +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum SimplifyParams { + Yes, + No, +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum StripReferences { + Yes, + No, +} + +/// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists. +/// +/// The idea is to get something simple that we can use to quickly decide if two types could unify, +/// for example during method lookup. /// -/// If `can_simplify_params` is false, then we will fail to simplify type parameters entirely. This -/// is useful when those type parameters would be instantiated with fresh type variables, since -/// then we can't say much about whether two types would unify. Put another way, -/// `can_simplify_params` should be true if type parameters appear free in `ty` and `false` if they -/// are to be considered bound. +/// A special case here are parameters and projections. Projections can be normalized to +/// a different type, meaning that `::Assoc` and `u8` can be unified, even though +/// their outermost layer is different while parameters like `T` of impls are later replaced +/// with an inference variable, which then also allows unification with other types. +/// +/// When using `SimplifyParams::Yes`, we still return a simplified type for params and projections², +/// the reasoning for this can be seen at the places doing this. +/// +/// For diagnostics we strip references with `StripReferences::Yes`. This is currently the best +/// way to skip some unhelpful suggestions. +/// +/// ¹ meaning that if two outermost layers are different, then the whole types are also different. +/// ² FIXME(@lcnr): this seems like it can actually end up being unsound with the way it's used during +/// candidate selection. We do not consider non blanket impls for `<_ as Trait>::Assoc` even +/// though `_` can be inferred to a concrete type later at which point a concrete impl +/// could actually apply. After experimenting for about an hour I wasn't able to cause any issues +/// this way so I am not going to change this until we actually find an issue as I am really +/// interesting in getting an actual test for this. pub fn simplify_type( tcx: TyCtxt<'_>, ty: Ty<'_>, - can_simplify_params: bool, + can_simplify_params: SimplifyParams, + strip_references: StripReferences, ) -> Option { match *ty.kind() { ty::Bool => Some(BoolSimplifiedType), @@ -67,19 +97,24 @@ pub fn simplify_type( ty::Float(float_type) => Some(FloatSimplifiedType(float_type)), ty::Adt(def, _) => Some(AdtSimplifiedType(def.did)), ty::Str => Some(StrSimplifiedType), - ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType), - ty::RawPtr(_) => Some(PtrSimplifiedType), + ty::Array(..) => Some(ArraySimplifiedType), + ty::Slice(..) => Some(SliceSimplifiedType), + ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)), ty::Dynamic(ref trait_info, ..) => match trait_info.principal_def_id() { Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => { Some(TraitSimplifiedType(principal_def_id)) } _ => Some(MarkerTraitObjectSimplifiedType), }, - ty::Ref(_, ty, _) => { - // since we introduce auto-refs during method lookup, we - // just treat &T and T as equivalent from the point of - // view of possibly unifying - simplify_type(tcx, ty, can_simplify_params) + ty::Ref(_, ty, mutbl) => { + if strip_references == StripReferences::Yes { + // For diagnostics, when recommending similar impls we want to + // recommend impls even when there is a reference mismatch, + // so we treat &T and T equivalently in that case. + simplify_type(tcx, ty, can_simplify_params, strip_references) + } else { + Some(RefSimplifiedType(mutbl)) + } } ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)), ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)), @@ -90,7 +125,7 @@ pub fn simplify_type( ty::Tuple(ref tys) => Some(TupleSimplifiedType(tys.len())), ty::FnPtr(ref f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), ty::Projection(_) | ty::Param(_) => { - if can_simplify_params { + if can_simplify_params == SimplifyParams::Yes { // In normalized types, projections don't unify with // anything. when lazy normalization happens, this // will change. It would still be nice to have a way @@ -120,9 +155,12 @@ impl SimplifiedTypeGen { UintSimplifiedType(t) => UintSimplifiedType(t), FloatSimplifiedType(t) => FloatSimplifiedType(t), AdtSimplifiedType(d) => AdtSimplifiedType(map(d)), + ForeignSimplifiedType(d) => ForeignSimplifiedType(map(d)), StrSimplifiedType => StrSimplifiedType, ArraySimplifiedType => ArraySimplifiedType, - PtrSimplifiedType => PtrSimplifiedType, + SliceSimplifiedType => SliceSimplifiedType, + RefSimplifiedType(m) => RefSimplifiedType(m), + PtrSimplifiedType(m) => PtrSimplifiedType(m), NeverSimplifiedType => NeverSimplifiedType, MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType, TupleSimplifiedType(n) => TupleSimplifiedType(n), @@ -133,7 +171,6 @@ impl SimplifiedTypeGen { OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)), FunctionSimplifiedType(n) => FunctionSimplifiedType(n), ParameterSimplifiedType => ParameterSimplifiedType, - ForeignSimplifiedType(d) => ForeignSimplifiedType(d), } } } @@ -149,12 +186,13 @@ where | CharSimplifiedType | StrSimplifiedType | ArraySimplifiedType - | PtrSimplifiedType + | SliceSimplifiedType | NeverSimplifiedType | ParameterSimplifiedType | MarkerTraitObjectSimplifiedType => { // nothing to do } + RefSimplifiedType(m) | PtrSimplifiedType(m) => m.hash_stable(hcx, hasher), IntSimplifiedType(t) => t.hash_stable(hcx, hasher), UintSimplifiedType(t) => t.hash_stable(hcx, hasher), FloatSimplifiedType(t) => t.hash_stable(hcx, hasher), diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 25a310b12db58..cbb88def7e27d 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -1,5 +1,5 @@ use crate::traits::specialization_graph; -use crate::ty::fast_reject; +use crate::ty::fast_reject::{self, SimplifyParams, StripReferences}; use crate::ty::fold::TypeFoldable; use crate::ty::{Ty, TyCtxt}; use rustc_hir as hir; @@ -146,6 +146,11 @@ impl<'tcx> TyCtxt<'tcx> { self_ty: Ty<'tcx>, mut f: F, ) -> Option { + // FIXME: This depends on the set of all impls for the trait. That is + // unfortunate wrt. incremental compilation. + // + // If we want to be faster, we could have separate queries for + // blanket and non-blanket impls, and compare them separately. let impls = self.trait_impls_of(def_id); for &impl_def_id in impls.blanket_impls.iter() { @@ -154,32 +159,16 @@ impl<'tcx> TyCtxt<'tcx> { } } - // simplify_type(.., false) basically replaces type parameters and - // projections with infer-variables. This is, of course, done on - // the impl trait-ref when it is instantiated, but not on the - // predicate trait-ref which is passed here. - // - // for example, if we match `S: Copy` against an impl like - // `impl Copy for Option`, we replace the type variable - // in `Option` with an infer variable, to `Option<_>` (this - // doesn't actually change fast_reject output), but we don't - // replace `S` with anything - this impl of course can't be - // selected, and as there are hundreds of similar impls, - // considering them would significantly harm performance. - - // This depends on the set of all impls for the trait. That is - // unfortunate. When we get red-green recompilation, we would like - // to have a way of knowing whether the set of relevant impls - // changed. The most naive - // way would be to compute the Vec of relevant impls and see whether - // it differs between compilations. That shouldn't be too slow by - // itself - we do quite a bit of work for each relevant impl anyway. - // - // If we want to be faster, we could have separate queries for - // blanket and non-blanket impls, and compare them separately. + // Note that we're using `SimplifyParams::Yes` to query `non_blanket_impls` while using + // `SimplifyParams::No` while actually adding them. // - // I think we'll cross that bridge when we get to it. - if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) { + // This way, when searching for some impl for `T: Trait`, we do not look at any impls + // whose outer level is not a parameter or projection. Especially for things like + // `T: Clone` this is incredibly useful as we would otherwise look at all the impls + // of `Clone` for `Option`, `Vec`, `ConcreteType` and so on. + if let Some(simp) = + fast_reject::simplify_type(self, self_ty, SimplifyParams::Yes, StripReferences::No) + { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { if let result @ Some(_) = f(impl_def_id) { @@ -238,7 +227,9 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait continue; } - if let Some(simplified_self_ty) = fast_reject::simplify_type(tcx, impl_self_ty, false) { + if let Some(simplified_self_ty) = + fast_reject::simplify_type(tcx, impl_self_ty, SimplifyParams::No, StripReferences::No) + { impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); } else { impls.blanket_impls.push(impl_def_id); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index aec9da9f8d4f8..5fac2e55b1d0d 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -12,9 +12,10 @@ use crate::traits::{ self, Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext, }; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, fast_reject, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::DUMMY_SP; use std::iter; @@ -82,12 +83,11 @@ where impl2_ref.iter().flat_map(|tref| tref.substs.types()), ) .any(|(ty1, ty2)| { - let t1 = fast_reject::simplify_type(tcx, ty1, false); - let t2 = fast_reject::simplify_type(tcx, ty2, false); + let t1 = fast_reject::simplify_type(tcx, ty1, SimplifyParams::No, StripReferences::No); + let t2 = fast_reject::simplify_type(tcx, ty2, SimplifyParams::No, StripReferences::No); if let (Some(t1), Some(t2)) = (t1, t2) { // Simplified successfully - // Types cannot unify if they differ in their reference mutability or simplify to different types - t1 != t2 || ty1.ref_mutability() != ty2.ref_mutability() + t1 != t2 } else { // Types might unify false diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 310eecc6e85f2..4e253e8fb6826 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -21,10 +21,10 @@ use rustc_hir::Item; use rustc_hir::Node; use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::ExpectedFound; +use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ - self, fast_reject, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, - TypeFoldable, + self, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, }; use rustc_session::DiagnosticMessageId; use rustc_span::symbol::{kw, sym}; @@ -1439,14 +1439,32 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { &self, trait_ref: ty::PolyTraitRef<'tcx>, ) -> Vec> { - let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true); + // We simplify params and strip references here. + // + // This both removes a lot of unhelpful suggestions, e.g. + // when searching for `&Foo: Trait` it doesn't suggestion `impl Trait for &Bar`, + // while also suggesting impls for `&Foo` when we're looking for `Foo: Trait`. + // + // The second thing isn't necessarily always a good thing, but + // any other simple setup results in a far worse output, so 🤷 + let simp = fast_reject::simplify_type( + self.tcx, + trait_ref.skip_binder().self_ty(), + SimplifyParams::Yes, + StripReferences::Yes, + ); let all_impls = self.tcx.all_impls(trait_ref.def_id()); match simp { Some(simp) => all_impls .filter_map(|def_id| { let imp = self.tcx.impl_trait_ref(def_id).unwrap(); - let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); + let imp_simp = fast_reject::simplify_type( + self.tcx, + imp.self_ty(), + SimplifyParams::Yes, + StripReferences::Yes, + ); if let Some(imp_simp) = imp_simp { if simp != imp_simp { return None; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2b120e855eb5a..607deb8f90875 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -35,7 +35,7 @@ use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir::abstract_const::NotConstEvaluatable; -use rustc_middle::ty::fast_reject; +use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef}; @@ -2089,10 +2089,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { |(obligation_arg, impl_arg)| { match (obligation_arg.unpack(), impl_arg.unpack()) { (GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => { - let simplified_obligation_ty = - fast_reject::simplify_type(self.tcx(), obligation_ty, true); - let simplified_impl_ty = - fast_reject::simplify_type(self.tcx(), impl_ty, false); + // Note, we simplify parameters for the obligation but not the + // impl so that we do not reject a blanket impl but do reject + // more concrete impls if we're searching for `T: Trait`. + let simplified_obligation_ty = fast_reject::simplify_type( + self.tcx(), + obligation_ty, + SimplifyParams::Yes, + StripReferences::No, + ); + let simplified_impl_ty = fast_reject::simplify_type( + self.tcx(), + impl_ty, + SimplifyParams::No, + StripReferences::No, + ); simplified_obligation_ty.is_some() && simplified_impl_ty.is_some() diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index ec7dcd4a419be..2f9d2c47b011f 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -2,7 +2,7 @@ use super::OverlapError; use crate::traits; use rustc_hir::def_id::DefId; -use rustc_middle::ty::fast_reject::{self, SimplifiedType}; +use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; @@ -48,7 +48,12 @@ impl ChildrenExt for Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); - if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { + if let Some(st) = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ) { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); self.non_blanket_impls.entry(st).or_default().push(impl_def_id) } else { @@ -63,7 +68,12 @@ impl ChildrenExt for Children { fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let vec: &mut Vec; - if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { + if let Some(st) = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ) { debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); vec = self.non_blanket_impls.get_mut(&st).unwrap(); } else { @@ -306,7 +316,12 @@ impl GraphExt for Graph { let mut parent = trait_def_id; let mut last_lint = None; - let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false); + let simplified = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ); // Descend the specialization tree, where `parent` is the current parent node. loop { diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 45b8e13d328c5..41c652616ca86 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -10,7 +10,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_middle::ty::fast_reject::simplify_type; +use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams, StripReferences}; use rustc_middle::ty::print::with_crate_prefix; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_span::lev_distance; @@ -1703,7 +1703,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: Even though negative bounds are not implemented, we could maybe handle // cases where a positive bound implies a negative impl. (candidates, Vec::new()) - } else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, true) { + } else if let Some(simp_rcvr_ty) = + simplify_type(self.tcx, rcvr_ty, SimplifyParams::Yes, StripReferences::No) + { let mut potential_candidates = Vec::new(); let mut explicitly_negative = Vec::new(); for candidate in candidates { @@ -1716,7 +1718,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .any(|imp_did| { let imp = self.tcx.impl_trait_ref(imp_did).unwrap(); - let imp_simp = simplify_type(self.tcx, imp.self_ty(), true); + let imp_simp = simplify_type( + self.tcx, + imp.self_ty(), + SimplifyParams::Yes, + StripReferences::No, + ); imp_simp.map_or(false, |s| s == simp_rcvr_ty) }) { diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr index c98925a7b1df7..8ce70b1ac0677 100644 --- a/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr +++ b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr @@ -4,7 +4,11 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied LL | is_defaulted::<&'static u32>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32` | - = note: required because of the requirements on the impl of `Defaulted` for `&'static u32` +note: required because of the requirements on the impl of `Defaulted` for `&'static u32` + --> $DIR/typeck-default-trait-impl-precedence.rs:10:19 + | +LL | impl<'a,T:Signed> Defaulted for &'a T { } + | ^^^^^^^^^ ^^^^^ note: required by a bound in `is_defaulted` --> $DIR/typeck-default-trait-impl-precedence.rs:12:19 | diff --git a/src/test/ui/impl-trait/issues/issue-70877.stderr b/src/test/ui/impl-trait/issues/issue-70877.stderr index b6861039f6a99..fe48e92da5eac 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.stderr @@ -5,8 +5,13 @@ LL | type FooRet = impl std::fmt::Debug; | -------------------- the found opaque type ... LL | type Foo = impl Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found opaque type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` | +note: expected this to be `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` + --> $DIR/issue-70877.rs:13:17 + | +LL | type Item = FooItem; + | ^^^^^^^ = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr index 7972437771399..355f2038df889 100644 --- a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr @@ -4,9 +4,6 @@ error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied LL | let _: &[i8] = data.into(); | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]` | - = help: the following implementations were found: - <[T; LANES] as From>> - <[bool; LANES] as From>> = note: required because of the requirements on the impl of `Into<&[i8]>` for `&[u8]` error: aborting due to previous error diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.stderr b/src/test/ui/wf/hir-wf-check-erase-regions.stderr index 0d9b9627562f9..aef6db0a40b75 100644 --- a/src/test/ui/wf/hir-wf-check-erase-regions.stderr +++ b/src/test/ui/wf/hir-wf-check-erase-regions.stderr @@ -5,7 +5,11 @@ LL | type IntoIter = std::iter::Flatten>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator | = help: the trait `Iterator` is not implemented for `&T` - = note: required because of the requirements on the impl of `IntoIterator` for `&T` +note: required because of the requirements on the impl of `IntoIterator` for `&T` + --> $DIR/hir-wf-check-erase-regions.rs:6:29 + | +LL | impl<'a, T, const N: usize> IntoIterator for &'a Table { + | ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ note: required by a bound in `Flatten` --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL | @@ -19,7 +23,11 @@ LL | fn into_iter(self) -> Self::IntoIter { | ^^^^^^^^^^^^^^ `&T` is not an iterator | = help: the trait `Iterator` is not implemented for `&T` - = note: required because of the requirements on the impl of `IntoIterator` for `&T` +note: required because of the requirements on the impl of `IntoIterator` for `&T` + --> $DIR/hir-wf-check-erase-regions.rs:6:29 + | +LL | impl<'a, T, const N: usize> IntoIterator for &'a Table { + | ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ note: required by a bound in `Flatten` --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL |