1
Fork 0

Support HIR wf checking for function signatures

During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.

This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.

As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).

As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
This commit is contained in:
Aaron Hill 2021-07-18 11:33:49 -05:00
parent da7d405357
commit db0324ebb2
No known key found for this signature in database
GPG key ID: B4087E510E98B164
28 changed files with 240 additions and 91 deletions

View file

@ -29,7 +29,10 @@ fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. }) Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. })
| Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. }) | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. })
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(&sig.decl), | 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, _ => None,
} }
} }

View file

@ -1722,7 +1722,7 @@ rustc_queries! {
/// span) for an *existing* error. Therefore, it is best-effort, and may never handle /// 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, /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine,
/// because the `ty::Ty`-based wfcheck is always run. /// because the `ty::Ty`-based wfcheck is always run.
query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, hir::HirId)) -> Option<traits::ObligationCause<'tcx>> { query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, traits::WellFormedLoc)) -> Option<traits::ObligationCause<'tcx>> {
eval_always eval_always
no_hash no_hash
desc { "performing HIR wf-checking for predicate {:?} at item {:?}", key.0, key.1 } desc { "performing HIR wf-checking for predicate {:?} at item {:?}", key.0, key.1 }

View file

@ -16,7 +16,7 @@ use crate::ty::{self, AdtKind, Ty, TyCtxt};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::Constness; use rustc_hir::Constness;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP}; 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` /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y`
OpaqueType, OpaqueType,
/// Well-formed checking. If a `HirId` is provided, /// Well-formed checking. If a `WellFormedLoc` is provided,
/// it is used to perform HIR-based wf checking if an error /// then it will be used to eprform HIR-based wf checking
/// occurs, in order to generate a more precise error message. /// after an error occurs, in order to generate a more precise error span.
/// This is purely for diagnostic purposes - it is always /// This is purely for diagnostic purposes - it is always
/// correct to use `MiscObligation` instead /// correct to use `MiscObligation` instead, or to specify
WellFormed(Option<hir::HirId>), /// `WellFormed(None)`
WellFormed(Option<WellFormedLoc>),
/// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against. /// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against.
MatchImpl(Lrc<ObligationCauseCode<'tcx>>, DefId), MatchImpl(Lrc<ObligationCauseCode<'tcx>>, 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<Foo>`).
#[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<'_> { impl ObligationCauseCode<'_> {
// Return the base obligation, ignoring derived obligations. // Return the base obligation, ignoring derived obligations.
pub fn peel_derives(&self) -> &Self { pub fn peel_derives(&self) -> &Self {

View file

@ -1682,7 +1682,7 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable
// This is the impl for `&'a InternalSubsts<'a>`. // This is the impl for `&'a InternalSubsts<'a>`.
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>} nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
CloneLiftImpls! { for<'tcx> { Constness, } } CloneLiftImpls! { for<'tcx> { Constness, traits::WellFormedLoc, } }
pub mod tls { pub mod tls {
use super::{ptr_eq, GlobalCtxt, TyCtxt}; use super::{ptr_eq, GlobalCtxt, TyCtxt};

View file

@ -1,9 +1,9 @@
//! Defines the set of legal keys that can be used in queries. //! 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::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::HirId;
use rustc_middle::infer::canonical::Canonical; use rustc_middle::infer::canonical::Canonical;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::traits;
use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::subst::{GenericArg, SubstsRef}; use rustc_middle::ty::subst::{GenericArg, SubstsRef};
use rustc_middle::ty::{self, Ty, TyCtxt}; 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)] #[inline(always)]
fn query_crate_is_local(&self) -> bool { fn query_crate_is_local(&self) -> bool {
true true

View file

@ -242,11 +242,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
SelectionError::Unimplemented => { SelectionError::Unimplemented => {
// If this obligation was generated as a result of well-formed checking, see if we // 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. // 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() root_obligation.cause.code.peel_derives()
{ {
if let Some(cause) = 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; obligation.cause = cause;
span = obligation.cause.span; span = obligation.cause.span;

View file

@ -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::error_reporting::InferCtxtExt as _;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt, self, ObligationCause, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt,
WellFormedLoc,
}; };
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
@ -419,13 +420,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self, &self,
span: Span, span: Span,
value: T, value: T,
hir_id: hir::HirId, loc: WellFormedLoc,
) -> T ) -> T
where where
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,
{ {
self.inh.normalize_associated_types_in_with_cause( 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, self.param_env,
value, value,
) )

View file

@ -22,8 +22,9 @@ use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::opaque_types::may_define_opaque_type; use rustc_trait_selection::opaque_types::may_define_opaque_type;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; 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::iter;
use std::ops::ControlFlow; use std::ops::ControlFlow;
@ -386,7 +387,7 @@ fn check_associated_item(
span: Span, span: Span,
sig_if_method: Option<&hir::FnSig<'_>>, 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| { for_id(tcx, item_id, span).with_fcx(|fcx| {
let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id)); 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 { match item.kind {
ty::AssocKind::Const => { ty::AssocKind::Const => {
let ty = fcx.tcx.type_of(item.def_id); 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()); fcx.register_wf_obligation(ty.into(), span, code.clone());
} }
ty::AssocKind::Fn => { ty::AssocKind::Fn => {
@ -422,7 +427,11 @@ fn check_associated_item(
} }
if item.defaultness.has_value() { if item.defaultness.has_value() {
let ty = fcx.tcx.type_of(item.def_id); 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()); 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| { for_id(tcx, item_id, ty_span).with_fcx(|fcx| {
let ty = tcx.type_of(tcx.hir().local_def_id(item_id)); 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; let mut forbid_unsized = true;
if allow_foreign_ty { 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( fcx.register_wf_obligation(
item_ty.into(), item_ty.into(),
ty_span, ty_span,
ObligationCauseCode::WellFormed(Some(item_id)), ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))),
); );
if forbid_unsized { if forbid_unsized {
fcx.register_bound( fcx.register_bound(
@ -684,7 +697,9 @@ fn check_impl<'tcx>(
fcx.register_wf_obligation( fcx.register_wf_obligation(
self_ty.into(), self_ty.into(),
ast_self_ty.span, 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<Ty<'tcx>>, implied_bounds: &mut Vec<Ty<'tcx>>,
) { ) {
let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig); 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) { // Normalize the input and output types one at a time, using a different
fcx.register_wf_obligation(input_ty.into(), ty.span, ObligationCauseCode::WellFormed(None)); // `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()); implied_bounds.extend(sig.inputs());
fcx.register_wf_obligation( fcx.register_wf_obligation(

View file

@ -3,10 +3,10 @@ use rustc_hir as hir;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::HirId; use rustc_hir::HirId;
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::TraitEngine; use rustc_infer::traits::TraitEngine;
use rustc_infer::traits::{ObligationCause, WellFormedLoc};
use rustc_middle::ty::query::Providers; 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; use rustc_trait_selection::traits;
pub fn provide(providers: &mut Providers) { pub fn provide(providers: &mut Providers) {
@ -17,21 +17,20 @@ pub fn provide(providers: &mut Providers) {
// need access to `ItemCtxt` // need access to `ItemCtxt`
fn diagnostic_hir_wf_check<'tcx>( fn diagnostic_hir_wf_check<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
(predicate, hir_id): (ty::Predicate<'tcx>, HirId), (predicate, loc): (ty::Predicate<'tcx>, WellFormedLoc),
) -> Option<ObligationCause<'tcx>> { ) -> Option<ObligationCause<'tcx>> {
let hir = tcx.hir(); 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). let def_id = match loc {
// It would be nice to extend this to handle wf checks inside functions. WellFormedLoc::Ty(def_id) => def_id,
let def_id = match tcx.hir().opt_local_def_id(hir_id) { WellFormedLoc::Param { function, param_idx: _ } => function,
Some(def_id) => def_id,
None => return None,
}; };
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()); let icx = ItemCtxt::new(tcx, def_id.to_def_id());
// To perform HIR-based WF checking, we iterate over all HIR types // 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>) { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
self.tcx.infer_ctxt().enter(|infcx| { self.tcx.infer_ctxt().enter(|infcx| {
let mut fulfill = traits::FulfillmentContext::new(); 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( let cause = traits::ObligationCause::new(
ty.span, ty.span,
self.hir_id, self.hir_id,
@ -119,19 +119,66 @@ fn diagnostic_hir_wf_check<'tcx>(
depth: 0, depth: 0,
}; };
let ty = match tcx.hir().get(hir_id) { // 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::Node::ImplItem(item) => match item.kind {
hir::ImplItemKind::TyAlias(ty) => Some(ty), hir::ImplItemKind::TyAlias(ty) => Some(ty),
_ => None, ref item => bug!("Unexpected ImplItem {:?}", item),
}, },
hir::Node::TraitItem(item) => match item.kind { hir::Node::TraitItem(item) => match item.kind {
hir::TraitItemKind::Type(_, ty) => ty, hir::TraitItemKind::Type(_, ty) => ty,
_ => None, ref item => bug!("Unexpected TraitItem {:?}", item),
}, },
_ => None, 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),
},
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 { if let Some(ty) = ty {
visitor.visit_ty(ty); visitor.visit_ty(ty);
} }
visitor.cause 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 }
}
}

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `Self: Get` is not satisfied 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<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {} LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
| ^^^^ the trait `Get` is not implemented for `Self` | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
| |
help: consider further restricting `Self` help: consider further restricting `Self`
| |

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `T: Get` is not satisfied 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<T>(foo: <T as Get>::Value) {} LL | fn uhoh<T>(foo: <T as Get>::Value) {}
| ^^^^ the trait `Get` is not implemented for `T` | ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
| |
help: consider restricting type parameter `T` help: consider restricting type parameter `T`
| |

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `Self: Get` is not satisfied 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<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {} LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
| ^^^^ the trait `Get` is not implemented for `Self` | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
| |
help: consider further restricting `Self` help: consider further restricting `Self`
| |

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `Self: Get` is not satisfied 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<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {} LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
| ^^^^ the trait `Get` is not implemented for `Self` | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
| |
help: consider further restricting `Self` help: consider further restricting `Self`
| |
@ -10,10 +13,13 @@ LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Ge
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error[E0277]: the trait bound `(T, U): Get` is not satisfied 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<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {} LL | fn uhoh<U:Get>(&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 error: aborting due to 2 previous errors

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `Self: Get` is not satisfied 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<U:Get>(&self, foo: U, bar: <Self as Get>::Value); LL | fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
| ^^^^ the trait `Get` is not implemented for `Self` | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
| |
help: consider further restricting `Self` help: consider further restricting `Self`
| |

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Foo` cannot be made into an object 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) { 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 = 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety> 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Trait` cannot be made into an object 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<dyn Trait>) { LL | fn call_foo(x: Box<dyn Trait>) {
| ^^^^^^^^^^^^^^ `Trait` cannot be made into an object | ^^^^^^^^^ `Trait` cannot be made into an object
| |
= help: consider moving `foo` to another trait = 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety> 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `NonObjectSafe1` cannot be made into an object 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<T>(obj: &dyn NonObjectSafe1) { LL | fn takes_non_object_safe_ref<T>(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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety> 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 --> $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 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<dyn NonObjectSafe3>) { LL | fn takes_non_object_safe_box(obj: Box<dyn NonObjectSafe3>) {
| ^^^^^^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object
| |
= help: consider moving `foo` to another trait = 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety> 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Foo` cannot be made into an object 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<dyn for<'a> Foo<A<'a> = &'a ()>>) {} LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
| |
= help: consider moving `A` to another trait = 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety> 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `X` cannot be made into an object 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<dyn X<Y<'a>=&'a ()>>) {} LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object | ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
| |
= help: consider moving `Y` to another trait = 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety> 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `StreamingIterator` cannot be made into an object 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<Item<'a> = &'a i32>) -> usize { LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
| |
= help: consider moving `Item` to another trait = 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety> 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `isize: HasState` is not satisfied 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: <isize as HasState>::State) { LL | fn add_state(op: <isize as HasState>::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 error: aborting due to previous error

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Bar` cannot be made into an object 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) { 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 = 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety> 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Trait` cannot be made into an object 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) {} 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 `baz` to another trait
= help: consider moving `bat` 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 | ^^^^ ...because method `bat` references the `Self` type in its return type
error[E0038]: the trait `Other` cannot be made into an object 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) {} 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety> 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-unsafe-trait-references-self.rs:8:14 --> $DIR/object-unsafe-trait-references-self.rs:8:14

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Trait` cannot be made into an object 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) {} 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety> 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8 --> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `(): Foo` is not satisfied 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; 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 error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied
--> $DIR/wf-foreign-fn-decl-ret.rs:14:32 --> $DIR/wf-foreign-fn-decl-ret.rs:14:32

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `T: Copy` is not satisfied 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<T:Copy> { LL | struct MustBeCopy<T:Copy> {
| ---- required by this bound in `MustBeCopy` | ---- required by this bound in `MustBeCopy`
... ...
LL | fn bar<T>(_: &MustBeCopy<T>) LL | fn bar<T>(_: &MustBeCopy<T>)
| ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
| |
help: consider restricting type parameter `T` help: consider restricting type parameter `T`
| |

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `Self: Eq` is not satisfied 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<T:Eq+?Sized> { value: Box<T> } LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
| -- required by this bound in `Bar` | -- required by this bound in `Bar`
... ...
LL | fn bar(&self, x: &Bar<Self>) { LL | fn bar(&self, x: &Bar<Self>) {
| ^^^^^^^^^^ the trait `Eq` is not implemented for `Self` | ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
| |
help: consider further restricting `Self` help: consider further restricting `Self`
| |

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `Self: Eq` is not satisfied 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<T:Eq+?Sized> { value: Box<T> } LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
| -- required by this bound in `Bar` | -- required by this bound in `Bar`
... ...
LL | fn bar(&self, x: &Bar<Self>); LL | fn bar(&self, x: &Bar<Self>);
| ^^^^^^^^^^ the trait `Eq` is not implemented for `Self` | ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
| |
help: consider further restricting `Self` help: consider further restricting `Self`
| |