diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 3d4c1835e4577..ecd370b240467 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -29,7 +29,10 @@ fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> { Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. }) | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(&sig.decl), - Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. }) => Some(fn_decl), + Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. }) + | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, ..), .. }) => { + Some(fn_decl) + } _ => None, } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index cb99ae19ee72e..0908b6a1763d5 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1722,7 +1722,7 @@ rustc_queries! { /// span) for an *existing* error. Therefore, it is best-effort, and may never handle /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine, /// because the `ty::Ty`-based wfcheck is always run. - query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, hir::HirId)) -> Option> { + query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, traits::WellFormedLoc)) -> Option> { eval_always no_hash desc { "performing HIR wf-checking for predicate {:?} at item {:?}", key.0, key.1 } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index f951e43fbfa35..a4a2e82463757 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -16,7 +16,7 @@ use crate::ty::{self, AdtKind, Ty, TyCtxt}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::Constness; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; @@ -327,17 +327,39 @@ pub enum ObligationCauseCode<'tcx> { /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y` OpaqueType, - /// Well-formed checking. If a `HirId` is provided, - /// it is used to perform HIR-based wf checking if an error - /// occurs, in order to generate a more precise error message. + /// Well-formed checking. If a `WellFormedLoc` is provided, + /// then it will be used to eprform HIR-based wf checking + /// after an error occurs, in order to generate a more precise error span. /// This is purely for diagnostic purposes - it is always - /// correct to use `MiscObligation` instead - WellFormed(Option), + /// correct to use `MiscObligation` instead, or to specify + /// `WellFormed(None)` + WellFormed(Option), /// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against. MatchImpl(Lrc>, DefId), } +/// The 'location' at which we try to perform HIR-based wf checking. +/// This information is used to obtain an `hir::Ty`, which +/// we can walk in order to obtain precise spans for any +/// 'nested' types (e.g. `Foo` in `Option`). +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +pub enum WellFormedLoc { + /// Use the type of the provided definition. + Ty(LocalDefId), + /// Use the type of the parameter of the provided function. + /// We cannot use `hir::Param`, since the function may + /// not have a body (e.g. a trait method definition) + Param { + /// The function to lookup the parameter in + function: LocalDefId, + /// The index of the parameter to use. + /// Parameters are indexed from 0, with the return type + /// being the last 'parameter' + param_idx: u16, + }, +} + impl ObligationCauseCode<'_> { // Return the base obligation, ignoring derived obligations. pub fn peel_derives(&self) -> &Self { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b84058011066f..4ce49032398bc 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1682,7 +1682,7 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable // This is the impl for `&'a InternalSubsts<'a>`. nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>} -CloneLiftImpls! { for<'tcx> { Constness, } } +CloneLiftImpls! { for<'tcx> { Constness, traits::WellFormedLoc, } } pub mod tls { use super::{ptr_eq, GlobalCtxt, TyCtxt}; diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 1993e0a602fa5..0ad360c7d89c3 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -1,9 +1,9 @@ //! Defines the set of legal keys that can be used in queries. use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; -use rustc_hir::HirId; use rustc_middle::infer::canonical::Canonical; use rustc_middle::mir; +use rustc_middle::traits; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::subst::{GenericArg, SubstsRef}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -397,7 +397,7 @@ impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) { } } -impl<'tcx> Key for (ty::Predicate<'tcx>, HirId) { +impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) { #[inline(always)] fn query_crate_is_local(&self) -> bool { true 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 5c4aef529e5ac..13a6733fb478a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -242,11 +242,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { SelectionError::Unimplemented => { // If this obligation was generated as a result of well-formed checking, see if we // can get a better error message by performing HIR-based well formed checking. - if let ObligationCauseCode::WellFormed(Some(wf_hir_id)) = + if let ObligationCauseCode::WellFormed(Some(wf_loc)) = root_obligation.cause.code.peel_derives() { if let Some(cause) = - self.tcx.diagnostic_hir_wf_check((obligation.predicate, *wf_hir_id)) + self.tcx.diagnostic_hir_wf_check((obligation.predicate, wf_loc.clone())) { obligation.cause = cause; span = obligation.cause.span; diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 4ed07ba358de3..865e4ccc0b63f 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -40,6 +40,7 @@ use rustc_trait_selection::opaque_types::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{ self, ObligationCause, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt, + WellFormedLoc, }; use std::collections::hash_map::Entry; @@ -419,13 +420,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, span: Span, value: T, - hir_id: hir::HirId, + loc: WellFormedLoc, ) -> T where T: TypeFoldable<'tcx>, { self.inh.normalize_associated_types_in_with_cause( - ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(Some(hir_id))), + ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(Some(loc))), self.param_env, value, ) diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index b24d63917c1cf..98980c65bc815 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -22,8 +22,9 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; use rustc_trait_selection::opaque_types::may_define_opaque_type; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; -use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc}; +use std::convert::TryInto; use std::iter; use std::ops::ControlFlow; @@ -386,7 +387,7 @@ fn check_associated_item( span: Span, sig_if_method: Option<&hir::FnSig<'_>>, ) { - let code = ObligationCauseCode::WellFormed(Some(item_id)); + let code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))); for_id(tcx, item_id, span).with_fcx(|fcx| { let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id)); @@ -400,7 +401,11 @@ fn check_associated_item( match item.kind { ty::AssocKind::Const => { let ty = fcx.tcx.type_of(item.def_id); - let ty = fcx.normalize_associated_types_in_wf(span, ty, item_id); + let ty = fcx.normalize_associated_types_in_wf( + span, + ty, + WellFormedLoc::Ty(item_id.expect_owner()), + ); fcx.register_wf_obligation(ty.into(), span, code.clone()); } ty::AssocKind::Fn => { @@ -422,7 +427,11 @@ fn check_associated_item( } if item.defaultness.has_value() { let ty = fcx.tcx.type_of(item.def_id); - let ty = fcx.normalize_associated_types_in_wf(span, ty, item_id); + let ty = fcx.normalize_associated_types_in_wf( + span, + ty, + WellFormedLoc::Ty(item_id.expect_owner()), + ); fcx.register_wf_obligation(ty.into(), span, code.clone()); } } @@ -621,7 +630,11 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo for_id(tcx, item_id, ty_span).with_fcx(|fcx| { let ty = tcx.type_of(tcx.hir().local_def_id(item_id)); - let item_ty = fcx.normalize_associated_types_in_wf(ty_span, ty, item_id); + let item_ty = fcx.normalize_associated_types_in_wf( + ty_span, + ty, + WellFormedLoc::Ty(item_id.expect_owner()), + ); let mut forbid_unsized = true; if allow_foreign_ty { @@ -634,7 +647,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo fcx.register_wf_obligation( item_ty.into(), ty_span, - ObligationCauseCode::WellFormed(Some(item_id)), + ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))), ); if forbid_unsized { fcx.register_bound( @@ -684,7 +697,9 @@ fn check_impl<'tcx>( fcx.register_wf_obligation( self_ty.into(), ast_self_ty.span, - ObligationCauseCode::WellFormed(Some(item.hir_id())), + ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty( + item.hir_id().expect_owner(), + ))), ); } } @@ -901,11 +916,48 @@ fn check_fn_or_method<'fcx, 'tcx>( implied_bounds: &mut Vec>, ) { let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig); - let sig = fcx.normalize_associated_types_in(span, sig); - for (&input_ty, ty) in iter::zip(sig.inputs(), hir_decl.inputs) { - fcx.register_wf_obligation(input_ty.into(), ty.span, ObligationCauseCode::WellFormed(None)); + // Normalize the input and output types one at a time, using a different + // `WellFormedLoc` for each. We cannot call `normalize_associated_types` + // on the entire `FnSig`, since this would use the same `WellFormedLoc` + // for each type, preventing the HIR wf check from generating + // a nice error message. + let ty::FnSig { mut inputs_and_output, c_variadic, unsafety, abi } = sig; + inputs_and_output = + fcx.tcx.mk_type_list(inputs_and_output.iter().enumerate().map(|(i, ty)| { + fcx.normalize_associated_types_in_wf( + span, + ty, + WellFormedLoc::Param { + function: def_id.expect_local(), + // Note that the `param_idx` of the output type is + // one greater than the index of the last input type. + param_idx: i.try_into().unwrap(), + }, + ) + })); + // Manually call `normalize_assocaited_types_in` on the other types + // in `FnSig`. This ensures that if the types of these fields + // ever change to include projections, we will start normalizing + // them automatically. + let sig = ty::FnSig { + inputs_and_output, + c_variadic: fcx.normalize_associated_types_in(span, c_variadic), + unsafety: fcx.normalize_associated_types_in(span, unsafety), + abi: fcx.normalize_associated_types_in(span, abi), + }; + + for (i, (&input_ty, ty)) in iter::zip(sig.inputs(), hir_decl.inputs).enumerate() { + fcx.register_wf_obligation( + input_ty.into(), + ty.span, + ObligationCauseCode::WellFormed(Some(WellFormedLoc::Param { + function: def_id.expect_local(), + param_idx: i.try_into().unwrap(), + })), + ); } + implied_bounds.extend(sig.inputs()); fcx.register_wf_obligation( diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_typeck/src/hir_wf_check.rs index a8ec7b79e571f..c1af10f5ce451 100644 --- a/compiler/rustc_typeck/src/hir_wf_check.rs +++ b/compiler/rustc_typeck/src/hir_wf_check.rs @@ -3,10 +3,10 @@ use rustc_hir as hir; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::HirId; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::ObligationCause; use rustc_infer::traits::TraitEngine; +use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, ToPredicate, TyCtxt}; +use rustc_middle::ty::{self, Region, ToPredicate, TyCtxt, TypeFoldable, TypeFolder}; use rustc_trait_selection::traits; pub fn provide(providers: &mut Providers) { @@ -17,21 +17,20 @@ pub fn provide(providers: &mut Providers) { // need access to `ItemCtxt` fn diagnostic_hir_wf_check<'tcx>( tcx: TyCtxt<'tcx>, - (predicate, hir_id): (ty::Predicate<'tcx>, HirId), + (predicate, loc): (ty::Predicate<'tcx>, WellFormedLoc), ) -> Option> { let hir = tcx.hir(); - // HIR wfcheck should only ever happen as part of improving an existing error - tcx.sess.delay_span_bug(hir.span(hir_id), "Performed HIR wfcheck without an existing error!"); - // Currently, we only handle WF checking for items (e.g. associated items). - // It would be nice to extend this to handle wf checks inside functions. - let def_id = match tcx.hir().opt_local_def_id(hir_id) { - Some(def_id) => def_id, - None => return None, + let def_id = match loc { + WellFormedLoc::Ty(def_id) => def_id, + WellFormedLoc::Param { function, param_idx: _ } => function, }; + let hir_id = HirId::make_owner(def_id); + + // HIR wfcheck should only ever happen as part of improving an existing error + tcx.sess + .delay_span_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!"); - // FIXME - figure out how we want to handle wf-checking for - // things inside a function body. let icx = ItemCtxt::new(tcx, def_id.to_def_id()); // To perform HIR-based WF checking, we iterate over all HIR types @@ -72,7 +71,8 @@ fn diagnostic_hir_wf_check<'tcx>( fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { self.tcx.infer_ctxt().enter(|infcx| { let mut fulfill = traits::FulfillmentContext::new(); - let tcx_ty = self.icx.to_ty(ty); + let tcx_ty = + self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx }); let cause = traits::ObligationCause::new( ty.span, self.hir_id, @@ -119,19 +119,66 @@ fn diagnostic_hir_wf_check<'tcx>( depth: 0, }; - let ty = match tcx.hir().get(hir_id) { - hir::Node::ImplItem(item) => match item.kind { - hir::ImplItemKind::TyAlias(ty) => Some(ty), - _ => None, - }, - hir::Node::TraitItem(item) => match item.kind { - hir::TraitItemKind::Type(_, ty) => ty, - _ => None, + // Get the starting `hir::Ty` using our `WellFormedLoc`. + // We will walk 'into' this type to try to find + // a more precise span for our predicate. + let ty = match loc { + WellFormedLoc::Ty(_) => match hir.get(hir_id) { + hir::Node::ImplItem(item) => match item.kind { + hir::ImplItemKind::TyAlias(ty) => Some(ty), + ref item => bug!("Unexpected ImplItem {:?}", item), + }, + hir::Node::TraitItem(item) => match item.kind { + hir::TraitItemKind::Type(_, ty) => ty, + ref item => bug!("Unexpected TraitItem {:?}", item), + }, + hir::Node::Item(item) => match item.kind { + hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => Some(ty), + hir::ItemKind::Impl(ref impl_) => { + assert!(impl_.of_trait.is_none(), "Unexpected trait impl: {:?}", impl_); + Some(impl_.self_ty) + } + ref item => bug!("Unexpected item {:?}", item), + }, + ref node => bug!("Unexpected node {:?}", node), }, - _ => None, + WellFormedLoc::Param { function: _, param_idx } => { + let fn_decl = hir.fn_decl_by_hir_id(hir_id).unwrap(); + // Get return type + if param_idx as usize == fn_decl.inputs.len() { + match fn_decl.output { + hir::FnRetTy::Return(ty) => Some(ty), + // The unit type `()` is always well-formed + hir::FnRetTy::DefaultReturn(_span) => None, + } + } else { + Some(&fn_decl.inputs[param_idx as usize]) + } + } }; if let Some(ty) = ty { visitor.visit_ty(ty); } visitor.cause } + +struct EraseAllBoundRegions<'tcx> { + tcx: TyCtxt<'tcx>, +} + +// Higher ranked regions are complicated. +// To make matters worse, the HIR WF check can instantiate them +// outside of a `Binder`, due to the way we (ab)use +// `ItemCtxt::to_ty`. To make things simpler, we just erase all +// of them, regardless of depth. At worse, this will give +// us an inaccurate span for an error message, but cannot +// lead to unsoundess (we call `delay_span_bug` at the start +// of `diagnostic_hir_wf_check`). +impl<'tcx> TypeFolder<'tcx> for EraseAllBoundRegions<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.tcx + } + fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { + if let ty::ReLateBound(..) = r { &ty::ReErased } else { r } + } +} diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr index e8c11a32bf7fd..25e80159b0b18 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-for-unimpl-trait.rs:10:8 + --> $DIR/associated-types-for-unimpl-trait.rs:10:40 | +LL | trait Get { + | --------- required by this bound in `Get` +... LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr index e3be434698ab9..19500f58aa688 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `T: Get` is not satisfied - --> $DIR/associated-types-no-suitable-bound.rs:11:8 + --> $DIR/associated-types-no-suitable-bound.rs:11:21 | +LL | trait Get { + | --------- required by this bound in `Get` +... LL | fn uhoh(foo: ::Value) {} - | ^^^^ the trait `Get` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr index 9dc3414e9edf0..0e978f20a6634 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:8 + --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40 | +LL | trait Get { + | --------- required by this bound in `Get` +... LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr index c2aed3f9de548..1ec3c05983aef 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait.rs:17:8 + --> $DIR/associated-types-no-suitable-supertrait.rs:17:40 | +LL | trait Get { + | --------- required by this bound in `Get` +... LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | @@ -10,10 +13,13 @@ LL | fn uhoh(&self, foo: U, bar: ::Value) where Self: Ge | ^^^^^^^^^^^^^^^ error[E0277]: the trait bound `(T, U): Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait.rs:22:8 + --> $DIR/associated-types-no-suitable-supertrait.rs:22:40 | +LL | trait Get { + | --------- required by this bound in `Get` +... LL | fn uhoh(&self, foo: U, bar: <(T, U) as Get>::Value) {} - | ^^^^ the trait `Get` is not implemented for `(T, U)` + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index fb842d968676d..b6ee1ed733c3e 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:8 + --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40 | +LL | trait Get { + | --------- required by this bound in `Get` +... LL | fn okay(&self, foo: U, bar: ::Value); - | ^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr index e0e6029252c00..319e6c2c032a0 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-err-ret.rs:17:15 + --> $DIR/object-safety-err-ret.rs:17:16 | LL | fn use_dyn(v: &dyn Foo) { - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` cannot be made into an object | = help: consider moving `test` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr index eb68a6298d1ac..cead9776e4abb 100644 --- a/src/test/ui/error-codes/E0038.stderr +++ b/src/test/ui/error-codes/E0038.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/E0038.rs:5:16 + --> $DIR/E0038.rs:5:20 | LL | fn call_foo(x: Box) { - | ^^^^^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` cannot be made into an object | = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr index 12195bc1071a0..c13c05f146a7e 100644 --- a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr +++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:38 + --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:39 | LL | fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { - | ^^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 @@ -35,10 +35,10 @@ LL | fn static_fn() where Self: Sized {} | ^^^^^^^^^^^^^^^^^ error[E0038]: the trait `NonObjectSafe3` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:35 + --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:39 | LL | fn takes_non_object_safe_box(obj: Box) { - | ^^^^^^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object | = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr index eb8e101a83d79..8651789688eaa 100644 --- a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/gat-in-trait-path.rs:21:13 + --> $DIR/gat-in-trait-path.rs:21:17 | LL | fn f(_arg : Box Foo = &'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | = help: consider moving `A` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.stderr index 8cc9f2816a166..b4b89ab047363 100644 --- a/src/test/ui/generic-associated-types/issue-67510-pass.stderr +++ b/src/test/ui/generic-associated-types/issue-67510-pass.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `X` cannot be made into an object - --> $DIR/issue-67510-pass.rs:7:19 + --> $DIR/issue-67510-pass.rs:7:23 | LL | fn _func1<'a>(_x: Box=&'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object | = help: consider moving `Y` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit diff --git a/src/test/ui/generic-associated-types/trait-objects.stderr b/src/test/ui/generic-associated-types/trait-objects.stderr index a121566bbd884..6429bb8159e1f 100644 --- a/src/test/ui/generic-associated-types/trait-objects.stderr +++ b/src/test/ui/generic-associated-types/trait-objects.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `StreamingIterator` cannot be made into an object - --> $DIR/trait-objects.rs:10:16 + --> $DIR/trait-objects.rs:10:21 | LL | fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object | = help: consider moving `Item` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit diff --git a/src/test/ui/issues/issue-18611.stderr b/src/test/ui/issues/issue-18611.stderr index 8872f51753c94..0e942e80e2544 100644 --- a/src/test/ui/issues/issue-18611.stderr +++ b/src/test/ui/issues/issue-18611.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `isize: HasState` is not satisfied - --> $DIR/issue-18611.rs:1:4 + --> $DIR/issue-18611.rs:1:18 | LL | fn add_state(op: ::State) { - | ^^^^^^^^^ the trait `HasState` is not implemented for `isize` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize` +... +LL | trait HasState { + | -------------- required by this bound in `HasState` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18959.stderr b/src/test/ui/issues/issue-18959.stderr index 86b530e85a80a..2a5416ce85ba6 100644 --- a/src/test/ui/issues/issue-18959.stderr +++ b/src/test/ui/issues/issue-18959.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-18959.rs:11:11 + --> $DIR/issue-18959.rs:11:12 | LL | fn foo(b: &dyn Bar) { - | ^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` cannot be made into an object | = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit diff --git a/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr b/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr index 797406f869fe6..f332b7213d8bc 100644 --- a/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr +++ b/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/object-unsafe-trait-references-self.rs:6:11 + --> $DIR/object-unsafe-trait-references-self.rs:6:12 | LL | fn bar(x: &dyn Trait) {} - | ^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` cannot be made into an object | = help: consider moving `baz` to another trait = help: consider moving `bat` to another trait @@ -17,10 +17,10 @@ LL | fn bat(&self) -> Self {} | ^^^^ ...because method `bat` references the `Self` type in its return type error[E0038]: the trait `Other` cannot be made into an object - --> $DIR/object-unsafe-trait-references-self.rs:10:11 + --> $DIR/object-unsafe-trait-references-self.rs:10:12 | LL | fn foo(x: &dyn Other) {} - | ^^^^^^^^^^ `Other` cannot be made into an object + | ^^^^^^^^^ `Other` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-unsafe-trait-references-self.rs:8:14 diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr index a2caf846cc5fe..4c18f6d79d077 100644 --- a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr +++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:11 + --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12 | LL | fn bar(x: &dyn Trait) {} - | ^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8 diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr index a0eb7d10bd94a..f6b48938f9b04 100644 --- a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr +++ b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/wf-foreign-fn-decl-ret.rs:11:12 + --> $DIR/wf-foreign-fn-decl-ret.rs:11:25 | +LL | pub trait Foo { + | ------------- required by this bound in `Foo` +... LL | pub fn lint_me() -> <() as Foo>::Assoc; - | ^^^^^^^ the trait `Foo` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied --> $DIR/wf-foreign-fn-decl-ret.rs:14:32 diff --git a/src/test/ui/wf/wf-in-fn-arg.stderr b/src/test/ui/wf/wf-in-fn-arg.stderr index 9687658feba43..ca90e9222dea9 100644 --- a/src/test/ui/wf/wf-in-fn-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-arg.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/wf-in-fn-arg.rs:10:14 + --> $DIR/wf-in-fn-arg.rs:10:15 | LL | struct MustBeCopy { | ---- required by this bound in `MustBeCopy` ... LL | fn bar(_: &MustBeCopy) - | ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/wf/wf-trait-default-fn-arg.stderr b/src/test/ui/wf/wf-trait-default-fn-arg.stderr index c3d5d2b9669b8..2a129538f7633 100644 --- a/src/test/ui/wf/wf-trait-default-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-arg.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied - --> $DIR/wf-trait-default-fn-arg.rs:11:22 + --> $DIR/wf-trait-default-fn-arg.rs:11:23 | LL | struct Bar { value: Box } | -- required by this bound in `Bar` ... LL | fn bar(&self, x: &Bar) { - | ^^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/wf/wf-trait-fn-arg.stderr b/src/test/ui/wf/wf-trait-fn-arg.stderr index 4510f50feea58..7693aa6d2d583 100644 --- a/src/test/ui/wf/wf-trait-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-fn-arg.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied - --> $DIR/wf-trait-fn-arg.rs:10:22 + --> $DIR/wf-trait-fn-arg.rs:10:23 | LL | struct Bar { value: Box } | -- required by this bound in `Bar` ... LL | fn bar(&self, x: &Bar); - | ^^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | help: consider further restricting `Self` |