diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 27643e715e6b1..3656afc43a3c3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -6,8 +6,8 @@ use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan; use rustc_middle::ty::{ - self, BottomUpFolder, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, - TypeVisitableExt, Upcast, + self, BottomUpFolder, DynKind, ExistentialPredicateStableCmpExt as _, Interner as _, Ty, + TyCtxt, TypeFoldable, TypeVisitableExt, Upcast, }; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; @@ -112,9 +112,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // let _: &dyn Alias = /* ... */; // ``` let mut projection_bounds = FxIndexMap::default(); + let mut auto_fill_bounds: SmallVec<[_; 4]> = smallvec![]; + let mut push_auto_fill_receiver_bound = |pred: ty::Binder<'tcx, _>| { + let receiver_target_did = + tcx.require_lang_item(rustc_hir::LangItem::ReceiverTarget, None); + let receiver_trait_ref = + tcx.anonymize_bound_vars(pred.map_bound(|proj: ty::ProjectionPredicate<'_>| { + tcx.trait_ref_and_own_args_for_alias( + receiver_target_did, + proj.projection_term.args, + ) + .0 + })); + let receiver_pred = pred.map_bound(|mut pred| { + pred.projection_term.def_id = receiver_target_did; + pred + }); + auto_fill_bounds.push((receiver_target_did, receiver_trait_ref, receiver_pred, span)); + }; for (proj, proj_span) in elaborated_projection_bounds { + debug!(?proj, "elaborated proj bound"); + let proj_did = proj.skip_binder().projection_term.def_id; let key = ( - proj.skip_binder().projection_term.def_id, + proj_did, tcx.anonymize_bound_vars( proj.map_bound(|proj| proj.projection_term.trait_ref(tcx)), ), @@ -142,6 +162,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) .emit(); } + if tcx.is_lang_item(proj_did, rustc_hir::LangItem::DerefTarget) { + push_auto_fill_receiver_bound(proj); + } } let principal_trait = regular_traits.into_iter().next(); @@ -221,6 +244,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if !projection_bounds.contains_key(&key) { projection_bounds.insert(key, (pred, supertrait_span)); } + if tcx.is_lang_item( + pred.skip_binder().def_id(), + rustc_hir::LangItem::DerefTarget, + ) { + // We need to fill in a `Receiver` bound because + // neither `Receiver` nor `Deref` is an auto-trait. + push_auto_fill_receiver_bound(pred); + } } self.check_elaborated_projection_mentions_input_lifetimes( @@ -233,6 +264,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } } + for (did, trait_ref, pred, span) in auto_fill_bounds { + if !projection_bounds.contains_key(&(did, trait_ref)) { + projection_bounds.insert((did, trait_ref), (pred, span)); + } + } // `dyn Trait` desugars to (not Rust syntax) `dyn Trait where // ::Assoc = Foo`. So every `Projection` clause is an @@ -264,6 +300,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } }) .collect(); + debug!(?missing_assoc_types, ?projection_bounds); if let Err(guar) = self.check_for_required_assoc_tys( principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()), @@ -378,6 +415,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .collect::>(); v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); let existential_predicates = tcx.mk_poly_existential_predicates(&v); + debug!(?existential_predicates); // Use explicitly-specified region bound, unless the bound is missing. let region_bound = if !lifetime.is_elided() { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 76a880da41855..6b53ac0a7273b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1036,90 +1036,108 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; debug!(?bound); - if let Some(bound2) = matching_candidates.next() { - debug!(?bound2); + let Some(bound2) = matching_candidates.next() else { return Ok(bound) }; + let mut matching_candidates = matching_candidates.peekable(); + + let is_receiver_target = |def_id| tcx.is_lang_item(def_id, rustc_hir::LangItem::Receiver); + let is_deref_target = |def_id| tcx.is_lang_item(def_id, rustc_hir::LangItem::Deref); + // Since `Deref::Target` and `Receiver::Target` are forced to be the same, + // the `Deref::Target` should be taken. + if assoc_name.name == sym::Target && matching_candidates.peek().is_none() { + if is_deref_target(bound.skip_binder().def_id) + && is_receiver_target(bound2.skip_binder().def_id) + { + return Ok(bound); + } + if is_receiver_target(bound.skip_binder().def_id) + && is_deref_target(bound2.skip_binder().def_id) + { + return Ok(bound2); + } + } - let assoc_kind_str = errors::assoc_kind_str(assoc_kind); - let qself_str = qself.to_string(tcx); - let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem { - span, - assoc_kind: assoc_kind_str, - assoc_name, - qself: &qself_str, - }); - // Provide a more specific error code index entry for equality bindings. - err.code( - if let Some(constraint) = constraint - && let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind - { - E0222 - } else { - E0221 - }, - ); + debug!(?bound2); - // FIXME(#97583): Print associated item bindings properly (i.e., not as equality predicates!). - // FIXME: Turn this into a structured, translateable & more actionable suggestion. - let mut where_bounds = vec![]; - for bound in [bound, bound2].into_iter().chain(matching_candidates) { - let bound_id = bound.def_id(); - let bound_span = tcx - .associated_items(bound_id) - .find_by_name_and_kind(tcx, assoc_name, assoc_kind, bound_id) - .and_then(|item| tcx.hir().span_if_local(item.def_id)); - - if let Some(bound_span) = bound_span { - err.span_label( - bound_span, - format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),), - ); - if let Some(constraint) = constraint { - match constraint.kind { - hir::AssocItemConstraintKind::Equality { term } => { - let term: ty::Term<'_> = match term { - hir::Term::Ty(ty) => self.lower_ty(ty).into(), - hir::Term::Const(ct) => { - self.lower_const_arg(ct, FeedConstTy::No).into() - } - }; - if term.references_error() { - continue; + let assoc_kind_str = errors::assoc_kind_str(assoc_kind); + let qself_str = qself.to_string(tcx); + let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem { + span, + assoc_kind: assoc_kind_str, + assoc_name, + qself: &qself_str, + }); + // Provide a more specific error code index entry for equality bindings. + err.code( + if let Some(constraint) = constraint + && let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind + { + E0222 + } else { + E0221 + }, + ); + + // FIXME(#97583): Print associated item bindings properly (i.e., not as equality predicates!). + // FIXME: Turn this into a structured, translateable & more actionable suggestion. + let mut where_bounds = vec![]; + for bound in [bound, bound2].into_iter().chain(matching_candidates) { + let bound_id = bound.def_id(); + let bound_span = tcx + .associated_items(bound_id) + .find_by_name_and_kind(tcx, assoc_name, assoc_kind, bound_id) + .and_then(|item| tcx.hir().span_if_local(item.def_id)); + + if let Some(bound_span) = bound_span { + err.span_label( + bound_span, + format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),), + ); + if let Some(constraint) = constraint { + match constraint.kind { + hir::AssocItemConstraintKind::Equality { term } => { + let term: ty::Term<'_> = match term { + hir::Term::Ty(ty) => self.lower_ty(ty).into(), + hir::Term::Const(ct) => { + self.lower_const_arg(ct, FeedConstTy::No).into() } - // FIXME(#97583): This isn't syntactically well-formed! - where_bounds.push(format!( - " T: {trait}::{assoc_name} = {term}", - trait = bound.print_only_trait_path(), - )); + }; + if term.references_error() { + continue; } - // FIXME: Provide a suggestion. - hir::AssocItemConstraintKind::Bound { bounds: _ } => {} + // FIXME(#97583): This isn't syntactically well-formed! + where_bounds.push(format!( + " T: {trait}::{assoc_name} = {term}", + trait = bound.print_only_trait_path(), + )); } - } else { - err.span_suggestion_verbose( - span.with_hi(assoc_name.span.lo()), - "use fully-qualified syntax to disambiguate", - format!("<{qself_str} as {}>::", bound.print_only_trait_path()), - Applicability::MaybeIncorrect, - ); + // FIXME: Provide a suggestion. + hir::AssocItemConstraintKind::Bound { bounds: _ } => {} } } else { - err.note(format!( - "associated {assoc_kind_str} `{assoc_name}` could derive from `{}`", - bound.print_only_trait_path(), - )); + err.span_suggestion_verbose( + span.with_hi(assoc_name.span.lo()), + "use fully-qualified syntax to disambiguate", + format!("<{qself_str} as {}>::", bound.print_only_trait_path()), + Applicability::MaybeIncorrect, + ); } - } - if !where_bounds.is_empty() { - err.help(format!( - "consider introducing a new type parameter `T` and adding `where` constraints:\ - \n where\n T: {qself_str},\n{}", - where_bounds.join(",\n"), + } else { + err.note(format!( + "associated {assoc_kind_str} `{assoc_name}` could derive from `{}`", + bound.print_only_trait_path(), )); - let reported = err.emit(); - return Err(reported); } - err.emit(); } + if !where_bounds.is_empty() { + err.help(format!( + "consider introducing a new type parameter `T` and adding `where` constraints:\ + \n where\n T: {qself_str},\n{}", + where_bounds.join(",\n"), + )); + let reported = err.emit(); + return Err(reported); + } + err.emit(); Ok(bound) } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3ef8ecc59e402..dbd8698faf7ca 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1392,6 +1392,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { if let Some(bound_principal) = predicates.principal() { self.wrap_binder(&bound_principal, WrapBinderMode::ForAll, |principal, cx| { define_scoped_cx!(cx); + let principal_deref_trait = + cx.tcx().is_lang_item(principal.def_id, LangItem::Deref); p!(print_def_path(principal.def_id, &[])); let mut resugared = false; @@ -1451,7 +1453,11 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { let super_proj = cx.tcx().anonymize_bound_vars(super_proj); proj == super_proj - }); + }) || (principal_deref_trait + && cx.tcx().is_lang_item( + proj.skip_binder().def_id, + LangItem::ReceiverTarget, + )); !proj_is_implied }) .map(|proj| { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 74a94d8278453..580375cd08d82 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -721,26 +721,23 @@ impl<'tcx> Ty<'tcx> { ) -> Ty<'tcx> { if cfg!(debug_assertions) { let projection_count = obj.projection_bounds().count(); - let expected_count: usize = obj - .principal_def_id() - .into_iter() - .flat_map(|principal_def_id| { - // NOTE: This should agree with `needed_associated_types` in - // dyn trait lowering, or else we'll have ICEs. - elaborate::supertraits( - tcx, - ty::Binder::dummy(ty::TraitRef::identity(tcx, principal_def_id)), - ) - .map(|principal| { - tcx.associated_items(principal.def_id()) - .in_definition_order() - .filter(|item| item.kind == ty::AssocKind::Type) - .filter(|item| !item.is_impl_trait_in_trait()) - .filter(|item| !tcx.generics_require_sized_self(item.def_id)) - .count() - }) + let expected_count = obj.principal_def_id().map_or(0, |principal_def_id| { + // NOTE: This should agree with `needed_associated_types` in + // dyn trait lowering, or else we'll have ICEs. + elaborate::supertraits( + tcx, + ty::Binder::dummy(ty::TraitRef::identity(tcx, principal_def_id)), + ) + .map(|principal| { + tcx.associated_items(principal.def_id()) + .in_definition_order() + .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| !item.is_impl_trait_in_trait()) + .filter(|item| !tcx.generics_require_sized_self(item.def_id)) + .count() }) - .sum(); + .sum() + }); assert_eq!( projection_count, expected_count, "expected {obj:?} to have {expected_count} projections, \ diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index e74f5443ac2d8..3e75f117445e5 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -128,6 +128,7 @@ /// let x = DerefExample { value: 'a' }; /// assert_eq!('a', *x); /// ``` +#[cfg(bootstrap)] #[lang = "deref"] #[doc(alias = "*")] #[doc(alias = "&*")] @@ -149,6 +150,158 @@ pub trait Deref { fn deref(&self) -> &Self::Target; } +/// Used for immutable dereferencing operations, like `*v`. +/// +/// In addition to being used for explicit dereferencing operations with the +/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly +/// by the compiler in many circumstances. This mechanism is called +/// ["`Deref` coercion"][coercion]. In mutable contexts, [`DerefMut`] is used and +/// mutable deref coercion similarly occurs. +/// +/// **Warning:** Deref coercion is a powerful language feature which has +/// far-reaching implications for every type that implements `Deref`. The +/// compiler will silently insert calls to `Deref::deref`. For this reason, one +/// should be careful about implementing `Deref` and only do so when deref +/// coercion is desirable. See [below][implementing] for advice on when this is +/// typically desirable or undesirable. +/// +/// Types that implement `Deref` or `DerefMut` are often called "smart +/// pointers" and the mechanism of deref coercion has been specifically designed +/// to facilitate the pointer-like behavior that name suggests. Often, the +/// purpose of a "smart pointer" type is to change the ownership semantics +/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the +/// storage semantics of a contained value (for example, [`Box`][box]). +/// +/// # Deref coercion +/// +/// If `T` implements `Deref`, and `v` is a value of type `T`, then: +/// +/// * In immutable contexts, `*v` (where `T` is neither a reference nor a raw +/// pointer) is equivalent to `*Deref::deref(&v)`. +/// * Values of type `&T` are coerced to values of type `&U` +/// * `T` implicitly implements all the methods of the type `U` which take the +/// `&self` receiver. +/// +/// For more details, visit [the chapter in *The Rust Programming Language*][book] +/// as well as the reference sections on [the dereference operator][ref-deref-op], +/// [method resolution], and [type coercions]. +/// +/// # When to implement `Deref` or `DerefMut` +/// +/// The same advice applies to both deref traits. In general, deref traits +/// **should** be implemented if: +/// +/// 1. a value of the type transparently behaves like a value of the target +/// type; +/// 1. the implementation of the deref function is cheap; and +/// 1. users of the type will not be surprised by any deref coercion behavior. +/// +/// In general, deref traits **should not** be implemented if: +/// +/// 1. the deref implementations could fail unexpectedly; or +/// 1. the type has methods that are likely to collide with methods on the +/// target type; or +/// 1. committing to deref coercion as part of the public API is not desirable. +/// +/// Note that there's a large difference between implementing deref traits +/// generically over many target types, and doing so only for specific target +/// types. +/// +/// Generic implementations, such as for [`Box`][box] (which is generic over +/// every type and dereferences to `T`) should be careful to provide few or no +/// methods, since the target type is unknown and therefore every method could +/// collide with one on the target type, causing confusion for users. +/// `impl Box` has no methods (though several associated functions), +/// partly for this reason. +/// +/// Specific implementations, such as for [`String`][string] (whose `Deref` +/// implementation has `Target = str`) can have many methods, since avoiding +/// collision is much easier. `String` and `str` both have many methods, and +/// `String` additionally behaves as if it has every method of `str` because of +/// deref coercion. The implementing type may also be generic while the +/// implementation is still specific in this sense; for example, [`Vec`][vec] +/// dereferences to `[T]`, so methods of `T` are not applicable. +/// +/// Consider also that deref coercion means that deref traits are a much larger +/// part of a type's public API than any other trait as it is implicitly called +/// by the compiler. Therefore, it is advisable to consider whether this is +/// something you are comfortable supporting as a public API. +/// +/// The [`AsRef`] and [`Borrow`][core::borrow::Borrow] traits have very similar +/// signatures to `Deref`. It may be desirable to implement either or both of +/// these, whether in addition to or rather than deref traits. See their +/// documentation for details. +/// +/// # Fallibility +/// +/// **This trait's method should never unexpectedly fail**. Deref coercion means +/// the compiler will often insert calls to `Deref::deref` implicitly. Failure +/// during dereferencing can be extremely confusing when `Deref` is invoked +/// implicitly. In the majority of uses it should be infallible, though it may +/// be acceptable to panic if the type is misused through programmer error, for +/// example. +/// +/// However, infallibility is not enforced and therefore not guaranteed. +/// As such, `unsafe` code should not rely on infallibility in general for +/// soundness. +/// +/// [book]: ../../book/ch15-02-deref.html +/// [coercion]: #deref-coercion +/// [implementing]: #when-to-implement-deref-or-derefmut +/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator +/// [method resolution]: ../../reference/expressions/method-call-expr.html +/// [type coercions]: ../../reference/type-coercions.html +/// [box]: ../../alloc/boxed/struct.Box.html +/// [string]: ../../alloc/string/struct.String.html +/// [vec]: ../../alloc/vec/struct.Vec.html +/// [rc]: ../../alloc/rc/struct.Rc.html +/// [cow]: ../../alloc/borrow/enum.Cow.html +/// +/// # Examples +/// +/// A struct with a single field which is accessible by dereferencing the +/// struct. +/// +/// ``` +/// use std::ops::Deref; +/// +/// struct DerefExample { +/// value: T +/// } +/// +/// impl Deref for DerefExample { +/// type Target = T; +/// +/// fn deref(&self) -> &Self::Target { +/// &self.value +/// } +/// } +/// +/// let x = DerefExample { value: 'a' }; +/// assert_eq!('a', *x); +/// ``` +#[cfg(not(bootstrap))] +#[lang = "deref"] +#[doc(alias = "*")] +#[doc(alias = "&*")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Deref"] +#[const_trait] +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +pub trait Deref: Receiver::Target> { + /// The resulting type after dereferencing. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "deref_target"] + #[lang = "deref_target"] + type Target: ?Sized; + + /// Dereferences the value. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "deref_method"] + fn deref(&self) -> &::Target; +} + #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_deref", issue = "88955")] impl const Deref for &T { @@ -271,7 +424,7 @@ pub trait DerefMut: ~const Deref { /// Mutably dereferences the value. #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "deref_mut_method"] - fn deref_mut(&mut self) -> &mut Self::Target; + fn deref_mut(&mut self) -> &mut ::Target; } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr index 8b6f0a47aed98..7c498fd33d3a9 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr @@ -1,68 +1,14 @@ -error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ `Self` cannot be formatted with the default formatter - | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:24:86 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^ required by this bound in `UncheckedCopy::Output` -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + std::fmt::Display { - | +++++++++++++++++++ - -error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-1.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ no implementation for `Self += &'static str` - | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:24:47 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { - | +++++++++++++++++++++++++ - error[E0277]: the trait bound `Self: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:24:96 + --> $DIR/defaults-unsound-62211-1.rs:22:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ the trait `Deref` is not implemented for `Self` | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:24:25 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` help: consider further restricting `Self` | LL | trait UncheckedCopy: Sized + Deref { | +++++++ -error[E0277]: the trait bound `Self: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ the trait `Copy` is not implemented for `Self` - | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:24:18 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ required by this bound in `UncheckedCopy::Output` -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + Copy { - | ++++++ - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr index 010f51df15ad3..7c498fd33d3a9 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr @@ -1,68 +1,14 @@ -error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ `Self` cannot be formatted with the default formatter - | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:24:86 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^ required by this bound in `UncheckedCopy::Output` -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + std::fmt::Display { - | +++++++++++++++++++ - -error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-1.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ no implementation for `Self += &'static str` - | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:24:47 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { - | +++++++++++++++++++++++++ - error[E0277]: the trait bound `Self: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:24:96 + --> $DIR/defaults-unsound-62211-1.rs:22:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ the trait `Deref` is not implemented for `Self` | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:24:31 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` help: consider further restricting `Self` | LL | trait UncheckedCopy: Sized + Deref { | +++++++ -error[E0277]: the trait bound `Self: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ the trait `Copy` is not implemented for `Self` - | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:24:18 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ required by this bound in `UncheckedCopy::Output` -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + Copy { - | ++++++ - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.rs b/tests/ui/associated-types/defaults-unsound-62211-1.rs index 124bac0ea721c..8e877865dbf39 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.rs +++ b/tests/ui/associated-types/defaults-unsound-62211-1.rs @@ -13,19 +13,14 @@ #![feature(associated_type_defaults)] -use std::{ - fmt::Display, - ops::{AddAssign, Deref}, -}; +use std::fmt::Display; +use std::ops::{AddAssign, Deref}; trait UncheckedCopy: Sized { // This Output is said to be Copy. Yet we default to Self - // and it's accepted, not knowing if Self ineed is Copy + // and it's accepted, not knowing if Self indeed is Copy type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - //~^ ERROR the trait bound `Self: Copy` is not satisfied - //~| ERROR the trait bound `Self: Deref` is not satisfied - //~| ERROR cannot add-assign `&'static str` to `Self` - //~| ERROR `Self` doesn't implement `std::fmt::Display` + //~^ ERROR the trait bound `Self: Deref` is not satisfied // We said the Output type was Copy, so we can Copy it freely! fn unchecked_copy(other: &Self::Output) -> Self::Output { diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr index 7552b08913337..5331286cfdbdf 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr @@ -1,68 +1,14 @@ -error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ `Self` cannot be formatted with the default formatter - | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:24:86 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^ required by this bound in `UncheckedCopy::Output` -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + std::fmt::Display { - | +++++++++++++++++++ - -error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-2.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ no implementation for `Self += &'static str` - | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:24:47 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { - | +++++++++++++++++++++++++ - error[E0277]: the trait bound `Self: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:24:96 + --> $DIR/defaults-unsound-62211-2.rs:22:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ the trait `Deref` is not implemented for `Self` | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:24:25 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` help: consider further restricting `Self` | LL | trait UncheckedCopy: Sized + Deref { | +++++++ -error[E0277]: the trait bound `Self: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ the trait `Copy` is not implemented for `Self` - | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:24:18 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ required by this bound in `UncheckedCopy::Output` -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + Copy { - | ++++++ - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr index 9347894657078..5331286cfdbdf 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr @@ -1,68 +1,14 @@ -error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ `Self` cannot be formatted with the default formatter - | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:24:86 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^ required by this bound in `UncheckedCopy::Output` -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + std::fmt::Display { - | +++++++++++++++++++ - -error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-2.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ no implementation for `Self += &'static str` - | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:24:47 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { - | +++++++++++++++++++++++++ - error[E0277]: the trait bound `Self: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:24:96 + --> $DIR/defaults-unsound-62211-2.rs:22:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ the trait `Deref` is not implemented for `Self` | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:24:31 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` help: consider further restricting `Self` | LL | trait UncheckedCopy: Sized + Deref { | +++++++ -error[E0277]: the trait bound `Self: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ the trait `Copy` is not implemented for `Self` - | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:24:18 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ required by this bound in `UncheckedCopy::Output` -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + Copy { - | ++++++ - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.rs b/tests/ui/associated-types/defaults-unsound-62211-2.rs index 998c39b5bad37..8e527b969f388 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.rs +++ b/tests/ui/associated-types/defaults-unsound-62211-2.rs @@ -13,19 +13,14 @@ #![feature(associated_type_defaults)] -use std::{ - fmt::Display, - ops::{AddAssign, Deref}, -}; +use std::fmt::Display; +use std::ops::{AddAssign, Deref}; trait UncheckedCopy: Sized { // This Output is said to be Copy. Yet we default to Self - // and it's accepted, not knowing if Self ineed is Copy + // and it's accepted, not knowing if Self indeed is Copy type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - //~^ ERROR the trait bound `Self: Copy` is not satisfied - //~| ERROR the trait bound `Self: Deref` is not satisfied - //~| ERROR cannot add-assign `&'static str` to `Self` - //~| ERROR `Self` doesn't implement `std::fmt::Display` + //~^ ERROR the trait bound `Self: Deref` is not satisfied // We said the Output type was Copy, so we can Copy it freely! fn unchecked_copy(other: &Self::Output) -> Self::Output { diff --git a/tests/ui/attributes/dump-preds.stderr b/tests/ui/attributes/dump-preds.stderr index bdfcbed71e9a6..89b17faffec18 100644 --- a/tests/ui/attributes/dump-preds.stderr +++ b/tests/ui/attributes/dump-preds.stderr @@ -33,6 +33,8 @@ LL | type Assoc: std::ops::Deref | = note: Binder { value: ProjectionPredicate(AliasTerm { args: [Alias(Projection, AliasTy { args: [Self/#0, T/#1, P/#2], def_id: DefId(..), .. })], def_id: DefId(..), .. }, Term::Ty(())), bound_vars: [] } = note: Binder { value: TraitPredicate(<>::Assoc

as std::ops::Deref>, polarity:Positive), bound_vars: [] } + = note: Binder { value: ProjectionPredicate(AliasTerm { args: [Alias(Projection, AliasTy { args: [Self/#0, T/#1, P/#2], def_id: DefId(..), .. })], def_id: DefId(..), .. }, Term::Ty(Alias(Projection, AliasTy { args: [Alias(Projection, AliasTy { args: [Self/#0, T/#1, P/#2], def_id: DefId(..), .. })], def_id: DefId(..), .. }))), bound_vars: [] } + = note: Binder { value: TraitPredicate(<>::Assoc

as std::ops::Receiver>, polarity:Positive), bound_vars: [] } = note: Binder { value: TraitPredicate(<>::Assoc

as std::marker::Sized>, polarity:Positive), bound_vars: [] } error: aborting due to 3 previous errors