Use fulfillment, not evaluate, during method probe
This commit is contained in:
parent
c13af7db21
commit
ff4653a08f
27 changed files with 328 additions and 407 deletions
|
@ -889,7 +889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
[candidate] => format!(
|
||||
"the method of the same name on {} `{}`",
|
||||
match candidate.kind {
|
||||
probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for",
|
||||
probe::CandidateKind::InherentImplCandidate(_) => "the inherent impl for",
|
||||
_ => "trait",
|
||||
},
|
||||
self.tcx.def_path_str(candidate.item.container_id(self.tcx))
|
||||
|
|
|
@ -31,13 +31,12 @@ use rustc_span::edit_distance::{
|
|||
};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
|
||||
use rustc_trait_selection::traits::query::method_autoderef::{
|
||||
CandidateStep, MethodAutoderefStepsResult,
|
||||
};
|
||||
use rustc_trait_selection::traits::query::CanonicalTyGoal;
|
||||
use rustc_trait_selection::traits::NormalizeExt;
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCause};
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::max;
|
||||
|
@ -99,39 +98,6 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct Candidate<'tcx> {
|
||||
// Candidates are (I'm not quite sure, but they are mostly) basically
|
||||
// some metadata on top of a `ty::AssocItem` (without args).
|
||||
//
|
||||
// However, method probing wants to be able to evaluate the predicates
|
||||
// for a function with the args applied - for example, if a function
|
||||
// has `where Self: Sized`, we don't want to consider it unless `Self`
|
||||
// is actually `Sized`, and similarly, return-type suggestions want
|
||||
// to consider the "actual" return type.
|
||||
//
|
||||
// The way this is handled is through `xform_self_ty`. It contains
|
||||
// the receiver type of this candidate, but `xform_self_ty`,
|
||||
// `xform_ret_ty` and `kind` (which contains the predicates) have the
|
||||
// generic parameters of this candidate instantiated with the *same set*
|
||||
// of inference variables, which acts as some weird sort of "query".
|
||||
//
|
||||
// When we check out a candidate, we require `xform_self_ty` to be
|
||||
// a subtype of the passed-in self-type, and this equates the type
|
||||
// variables in the rest of the fields.
|
||||
//
|
||||
// For example, if we have this candidate:
|
||||
// ```
|
||||
// trait Foo {
|
||||
// fn foo(&self) where Self: Sized;
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Then `xform_self_ty` will be `&'erased ?X` and `kind` will contain
|
||||
// the predicate `?X: Sized`, so if we are evaluating `Foo` for a
|
||||
// the receiver `&T`, we'll do the subtyping which will make `?X`
|
||||
// get the right value, then when we evaluate the predicate we'll check
|
||||
// if `T: Sized`.
|
||||
xform_self_ty: Ty<'tcx>,
|
||||
xform_ret_ty: Option<Ty<'tcx>>,
|
||||
pub(crate) item: ty::AssocItem,
|
||||
pub(crate) kind: CandidateKind<'tcx>,
|
||||
pub(crate) import_ids: SmallVec<[LocalDefId; 1]>,
|
||||
|
@ -139,17 +105,10 @@ pub(crate) struct Candidate<'tcx> {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum CandidateKind<'tcx> {
|
||||
InherentImplCandidate(
|
||||
GenericArgsRef<'tcx>,
|
||||
// Normalize obligations
|
||||
Vec<traits::PredicateObligation<'tcx>>,
|
||||
),
|
||||
ObjectCandidate,
|
||||
TraitCandidate(ty::TraitRef<'tcx>),
|
||||
WhereClauseCandidate(
|
||||
// Trait
|
||||
ty::PolyTraitRef<'tcx>,
|
||||
),
|
||||
InherentImplCandidate(DefId),
|
||||
ObjectCandidate(ty::PolyTraitRef<'tcx>),
|
||||
TraitCandidate(ty::PolyTraitRef<'tcx>),
|
||||
WhereClauseCandidate(ty::PolyTraitRef<'tcx>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
|
@ -743,41 +702,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
self.record_static_candidate(CandidateSource::Impl(impl_def_id));
|
||||
continue;
|
||||
}
|
||||
|
||||
let (impl_ty, impl_args) = self.impl_ty_and_args(impl_def_id);
|
||||
|
||||
debug!("impl_ty: {:?}", impl_ty);
|
||||
|
||||
// Determine the receiver type that the method itself expects.
|
||||
let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(item, impl_ty, impl_args);
|
||||
debug!("xform_self_ty: {:?}, xform_ret_ty: {:?}", xform_self_ty, xform_ret_ty);
|
||||
|
||||
// We can't use `FnCtxt::normalize` as it will pollute the
|
||||
// fcx's fulfillment context after this probe is over.
|
||||
//
|
||||
// Note: we only normalize `xform_self_ty` here since the normalization
|
||||
// of the return type can lead to inference results that prohibit
|
||||
// valid candidates from being found, see issue #85671
|
||||
//
|
||||
// FIXME Postponing the normalization of the return type likely only hides a deeper bug,
|
||||
// which might be caused by the `param_env` itself. The clauses of the `param_env`
|
||||
// maybe shouldn't include `Param`s, but rather fresh variables or be canonicalized,
|
||||
// see issue #89650
|
||||
let cause = traits::ObligationCause::misc(self.span, self.body_id);
|
||||
let InferOk { value: xform_self_ty, obligations } =
|
||||
self.fcx.at(&cause, self.param_env).normalize(xform_self_ty);
|
||||
|
||||
debug!(
|
||||
"assemble_inherent_impl_probe after normalization: xform_self_ty = {:?}/{:?}",
|
||||
xform_self_ty, xform_ret_ty
|
||||
);
|
||||
|
||||
self.push_candidate(
|
||||
Candidate {
|
||||
xform_self_ty,
|
||||
xform_ret_ty,
|
||||
item,
|
||||
kind: InherentImplCandidate(impl_args, obligations),
|
||||
kind: InherentImplCandidate(impl_def_id),
|
||||
import_ids: smallvec![],
|
||||
},
|
||||
true,
|
||||
|
@ -809,26 +737,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
// a `&self` method will wind up with an argument type like `&dyn Trait`.
|
||||
let trait_ref = principal.with_self_ty(self.tcx, self_ty);
|
||||
self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| {
|
||||
if new_trait_ref.has_non_region_bound_vars() {
|
||||
this.dcx().span_delayed_bug(
|
||||
this.span,
|
||||
"tried to select method from HRTB with non-lifetime bound vars",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let new_trait_ref = this.tcx.instantiate_bound_regions_with_erased(new_trait_ref);
|
||||
|
||||
let (xform_self_ty, xform_ret_ty) =
|
||||
this.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args);
|
||||
this.push_candidate(
|
||||
Candidate {
|
||||
xform_self_ty,
|
||||
xform_ret_ty,
|
||||
item,
|
||||
kind: ObjectCandidate,
|
||||
import_ids: smallvec![],
|
||||
},
|
||||
Candidate { item, kind: ObjectCandidate(new_trait_ref), import_ids: smallvec![] },
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
@ -859,19 +769,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
});
|
||||
|
||||
self.elaborate_bounds(bounds, |this, poly_trait_ref, item| {
|
||||
let trait_ref = this.instantiate_binder_with_fresh_vars(
|
||||
this.span,
|
||||
infer::BoundRegionConversionTime::FnCall,
|
||||
poly_trait_ref,
|
||||
);
|
||||
|
||||
let (xform_self_ty, xform_ret_ty) =
|
||||
this.xform_self_ty(item, trait_ref.self_ty(), trait_ref.args);
|
||||
|
||||
this.push_candidate(
|
||||
Candidate {
|
||||
xform_self_ty,
|
||||
xform_ret_ty,
|
||||
item,
|
||||
kind: WhereClauseCandidate(poly_trait_ref),
|
||||
import_ids: smallvec![],
|
||||
|
@ -962,21 +861,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
bound_trait_ref.def_id(),
|
||||
));
|
||||
} else {
|
||||
let new_trait_ref = self.instantiate_binder_with_fresh_vars(
|
||||
self.span,
|
||||
infer::BoundRegionConversionTime::FnCall,
|
||||
bound_trait_ref,
|
||||
);
|
||||
|
||||
let (xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args);
|
||||
self.push_candidate(
|
||||
Candidate {
|
||||
xform_self_ty,
|
||||
xform_ret_ty,
|
||||
item,
|
||||
import_ids: import_ids.clone(),
|
||||
kind: TraitCandidate(new_trait_ref),
|
||||
kind: TraitCandidate(bound_trait_ref),
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -995,16 +884,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
self.record_static_candidate(CandidateSource::Trait(trait_def_id));
|
||||
continue;
|
||||
}
|
||||
|
||||
let (xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(item, trait_ref.self_ty(), trait_args);
|
||||
self.push_candidate(
|
||||
Candidate {
|
||||
xform_self_ty,
|
||||
xform_ret_ty,
|
||||
item,
|
||||
import_ids: import_ids.clone(),
|
||||
kind: TraitCandidate(trait_ref),
|
||||
kind: TraitCandidate(ty::Binder::dummy(trait_ref)),
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1434,16 +1318,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
|
||||
fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource {
|
||||
match candidate.kind {
|
||||
InherentImplCandidate(..) => {
|
||||
InherentImplCandidate(_) => {
|
||||
CandidateSource::Impl(candidate.item.container_id(self.tcx))
|
||||
}
|
||||
ObjectCandidate | WhereClauseCandidate(_) => {
|
||||
ObjectCandidate(_) | WhereClauseCandidate(_) => {
|
||||
CandidateSource::Trait(candidate.item.container_id(self.tcx))
|
||||
}
|
||||
TraitCandidate(trait_ref) => self.probe(|_| {
|
||||
let trait_ref =
|
||||
self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, trait_ref);
|
||||
let (xform_self_ty, _) =
|
||||
self.xform_self_ty(candidate.item, trait_ref.self_ty(), trait_ref.args);
|
||||
let _ = self.at(&ObligationCause::dummy(), self.param_env).sup(
|
||||
DefineOpaqueTypes::No,
|
||||
candidate.xform_self_ty,
|
||||
xform_self_ty,
|
||||
self_ty,
|
||||
);
|
||||
match self.select_trait_candidate(trait_ref) {
|
||||
|
@ -1470,54 +1358,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
) -> ProbeResult {
|
||||
debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe);
|
||||
|
||||
self.probe(|_| {
|
||||
// First check that the self type can be related.
|
||||
let sub_obligations = match self.at(&ObligationCause::dummy(), self.param_env).sup(
|
||||
DefineOpaqueTypes::No,
|
||||
probe.xform_self_ty,
|
||||
self_ty,
|
||||
) {
|
||||
Ok(InferOk { obligations, value: () }) => obligations,
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
}
|
||||
};
|
||||
self.probe(|snapshot| {
|
||||
let outer_universe = self.universe();
|
||||
|
||||
let mut result = ProbeResult::Match;
|
||||
let mut xform_ret_ty = probe.xform_ret_ty;
|
||||
debug!(?xform_ret_ty);
|
||||
let cause = &self.misc(self.span);
|
||||
let ocx = ObligationCtxt::new(self);
|
||||
|
||||
let cause = traits::ObligationCause::misc(self.span, self.body_id);
|
||||
let mut trait_predicate = None;
|
||||
let (mut xform_self_ty, mut xform_ret_ty);
|
||||
|
||||
let mut parent_pred = None;
|
||||
|
||||
// If so, impls may carry other conditions (e.g., where
|
||||
// clauses) that must be considered. Make sure that those
|
||||
// match as well (or at least may match, sometimes we
|
||||
// don't have enough information to fully evaluate).
|
||||
match probe.kind {
|
||||
InherentImplCandidate(args, ref ref_obligations) => {
|
||||
// `xform_ret_ty` hasn't been normalized yet, only `xform_self_ty`,
|
||||
// see the reasons mentioned in the comments in `assemble_inherent_impl_probe`
|
||||
// for why this is necessary
|
||||
let InferOk {
|
||||
value: normalized_xform_ret_ty,
|
||||
obligations: normalization_obligations,
|
||||
} = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty);
|
||||
xform_ret_ty = normalized_xform_ret_ty;
|
||||
debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty);
|
||||
|
||||
InherentImplCandidate(impl_def_id) => {
|
||||
let impl_args = self.fresh_args_for_item(self.span, impl_def_id);
|
||||
let impl_ty = self.tcx.type_of(impl_def_id).instantiate(self.tcx, impl_args);
|
||||
(xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(probe.item, impl_ty, impl_args);
|
||||
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
|
||||
// FIXME: Weirdly, we normalize the ret ty in this candidate, but no other candidates.
|
||||
xform_ret_ty = ocx.normalize(cause, self.param_env, xform_ret_ty);
|
||||
match ocx.eq_no_opaques(cause, self.param_env, xform_self_ty, self_ty) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
}
|
||||
}
|
||||
// Check whether the impl imposes obligations we have to worry about.
|
||||
let impl_def_id = probe.item.container_id(self.tcx);
|
||||
let impl_bounds = self.tcx.predicates_of(impl_def_id);
|
||||
let impl_bounds = impl_bounds.instantiate(self.tcx, args);
|
||||
|
||||
let InferOk { value: impl_bounds, obligations: norm_obligations } =
|
||||
self.fcx.at(&cause, self.param_env).normalize(impl_bounds);
|
||||
|
||||
let impl_bounds =
|
||||
self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args);
|
||||
let impl_bounds = ocx.normalize(cause, self.param_env, impl_bounds);
|
||||
// Convert the bounds into obligations.
|
||||
let impl_obligations = traits::predicates_for_generics(
|
||||
ocx.register_obligations(traits::predicates_for_generics(
|
||||
|idx, span| {
|
||||
let code = if span.is_dummy() {
|
||||
traits::ExprItemObligation(impl_def_id, self.scope_expr_id, idx)
|
||||
|
@ -1533,106 +1406,56 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
},
|
||||
self.param_env,
|
||||
impl_bounds,
|
||||
);
|
||||
|
||||
let candidate_obligations = impl_obligations
|
||||
.chain(norm_obligations)
|
||||
.chain(ref_obligations.iter().cloned())
|
||||
.chain(normalization_obligations);
|
||||
|
||||
// Evaluate those obligations to see if they might possibly hold.
|
||||
for o in candidate_obligations {
|
||||
let o = self.resolve_vars_if_possible(o);
|
||||
if !self.predicate_may_hold(&o) {
|
||||
result = ProbeResult::NoMatch;
|
||||
let parent_o = o.clone();
|
||||
let implied_obligations = traits::elaborate(self.tcx, vec![o]);
|
||||
for o in implied_obligations {
|
||||
let parent = if o == parent_o {
|
||||
None
|
||||
} else {
|
||||
if o.predicate.to_opt_poly_trait_pred().map(|p| p.def_id())
|
||||
== self.tcx.lang_items().sized_trait()
|
||||
{
|
||||
// We don't care to talk about implicit `Sized` bounds.
|
||||
continue;
|
||||
}
|
||||
Some(parent_o.predicate)
|
||||
};
|
||||
if !self.predicate_may_hold(&o) {
|
||||
possibly_unsatisfied_predicates.push((
|
||||
o.predicate,
|
||||
parent,
|
||||
Some(o.cause),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
ObjectCandidate | WhereClauseCandidate(..) => {
|
||||
// These have no additional conditions to check.
|
||||
}
|
||||
|
||||
TraitCandidate(trait_ref) => {
|
||||
TraitCandidate(poly_trait_ref) => {
|
||||
// Some trait methods are excluded for arrays before 2021.
|
||||
// (`array.into_iter()` wants a slice iterator for compatibility.)
|
||||
if let Some(method_name) = self.method_name {
|
||||
// Some trait methods are excluded for arrays before 2021.
|
||||
// (`array.into_iter()` wants a slice iterator for compatibility.)
|
||||
if self_ty.is_array() && !method_name.span.at_least_rust_2021() {
|
||||
let trait_def = self.tcx.trait_def(trait_ref.def_id);
|
||||
let trait_def = self.tcx.trait_def(poly_trait_ref.def_id());
|
||||
if trait_def.skip_array_during_method_dispatch {
|
||||
return ProbeResult::NoMatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
let predicate = ty::Binder::dummy(trait_ref).to_predicate(self.tcx);
|
||||
parent_pred = Some(predicate);
|
||||
let obligation =
|
||||
traits::Obligation::new(self.tcx, cause.clone(), self.param_env, predicate);
|
||||
if !self.predicate_may_hold(&obligation) {
|
||||
result = ProbeResult::NoMatch;
|
||||
if self.probe(|_| {
|
||||
match self.select_trait_candidate(trait_ref) {
|
||||
Err(_) => return true,
|
||||
Ok(Some(impl_source))
|
||||
if !impl_source.borrow_nested_obligations().is_empty() =>
|
||||
{
|
||||
for obligation in impl_source.borrow_nested_obligations() {
|
||||
// Determine exactly which obligation wasn't met, so
|
||||
// that we can give more context in the error.
|
||||
if !self.predicate_may_hold(obligation) {
|
||||
let nested_predicate =
|
||||
self.resolve_vars_if_possible(obligation.predicate);
|
||||
let predicate =
|
||||
self.resolve_vars_if_possible(predicate);
|
||||
let p = if predicate == nested_predicate {
|
||||
// Avoid "`MyStruct: Foo` which is required by
|
||||
// `MyStruct: Foo`" in E0599.
|
||||
None
|
||||
} else {
|
||||
Some(predicate)
|
||||
};
|
||||
possibly_unsatisfied_predicates.push((
|
||||
nested_predicate,
|
||||
p,
|
||||
Some(obligation.cause.clone()),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Some nested subobligation of this predicate
|
||||
// failed.
|
||||
let predicate = self.resolve_vars_if_possible(predicate);
|
||||
possibly_unsatisfied_predicates.push((predicate, None, None));
|
||||
}
|
||||
}
|
||||
false
|
||||
}) {
|
||||
// This candidate's primary obligation doesn't even
|
||||
// select - don't bother registering anything in
|
||||
// `potentially_unsatisfied_predicates`.
|
||||
|
||||
let trait_ref = self.instantiate_binder_with_fresh_vars(
|
||||
self.span,
|
||||
infer::FnCall,
|
||||
poly_trait_ref,
|
||||
);
|
||||
(xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
|
||||
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
|
||||
match ocx.eq_no_opaques(cause, self.param_env, xform_self_ty, self_ty) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
}
|
||||
}
|
||||
ocx.register_obligation(traits::Obligation::new(
|
||||
self.tcx,
|
||||
cause.clone(),
|
||||
self.param_env,
|
||||
ty::Binder::dummy(trait_ref),
|
||||
));
|
||||
trait_predicate = Some(ty::Binder::dummy(trait_ref).to_predicate(self.tcx));
|
||||
}
|
||||
ObjectCandidate(poly_trait_ref) | WhereClauseCandidate(poly_trait_ref) => {
|
||||
let trait_ref = self.instantiate_binder_with_fresh_vars(
|
||||
self.span,
|
||||
infer::FnCall,
|
||||
poly_trait_ref,
|
||||
);
|
||||
(xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
|
||||
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
|
||||
match ocx.eq_no_opaques(cause, self.param_env, xform_self_ty, self_ty) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
}
|
||||
}
|
||||
|
@ -1640,11 +1463,22 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// Evaluate those obligations to see if they might possibly hold.
|
||||
for o in sub_obligations {
|
||||
let o = self.resolve_vars_if_possible(o);
|
||||
if !self.predicate_may_hold(&o) {
|
||||
result = ProbeResult::NoMatch;
|
||||
possibly_unsatisfied_predicates.push((o.predicate, parent_pred, Some(o.cause)));
|
||||
for error in ocx.select_where_possible() {
|
||||
result = ProbeResult::NoMatch;
|
||||
let nested_predicate = self.resolve_vars_if_possible(error.obligation.predicate);
|
||||
if let Some(trait_predicate) = trait_predicate
|
||||
&& nested_predicate == self.resolve_vars_if_possible(trait_predicate)
|
||||
{
|
||||
// Don't report possibly unsatisfied predicates if the root
|
||||
// trait obligation from a `TraitCandidate` is unsatisfied.
|
||||
// That just means the candidate doesn't hold.
|
||||
} else {
|
||||
possibly_unsatisfied_predicates.push((
|
||||
nested_predicate,
|
||||
Some(self.resolve_vars_if_possible(error.root_obligation.predicate))
|
||||
.filter(|root_predicate| *root_predicate != nested_predicate),
|
||||
Some(error.obligation.cause),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1656,36 +1490,37 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
// We don't normalize the other candidates for perf/backwards-compat reasons...
|
||||
// but `self.return_type` is only set on the diagnostic-path, so we
|
||||
// should be okay doing it here.
|
||||
if !matches!(probe.kind, InherentImplCandidate(..)) {
|
||||
let InferOk {
|
||||
value: normalized_xform_ret_ty,
|
||||
obligations: normalization_obligations,
|
||||
} = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty);
|
||||
xform_ret_ty = normalized_xform_ret_ty;
|
||||
debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty);
|
||||
// Evaluate those obligations to see if they might possibly hold.
|
||||
for o in normalization_obligations {
|
||||
let o = self.resolve_vars_if_possible(o);
|
||||
if !self.predicate_may_hold(&o) {
|
||||
result = ProbeResult::NoMatch;
|
||||
possibly_unsatisfied_predicates.push((
|
||||
o.predicate,
|
||||
None,
|
||||
Some(o.cause),
|
||||
));
|
||||
}
|
||||
}
|
||||
if !matches!(probe.kind, InherentImplCandidate(_)) {
|
||||
xform_ret_ty = ocx.normalize(&cause, self.param_env, xform_ret_ty);
|
||||
}
|
||||
|
||||
debug!("comparing return_ty {:?} with xform ret ty {:?}", return_ty, xform_ret_ty);
|
||||
if let ProbeResult::Match = result
|
||||
&& self
|
||||
.at(&ObligationCause::dummy(), self.param_env)
|
||||
.sup(DefineOpaqueTypes::Yes, return_ty, xform_ret_ty)
|
||||
.is_err()
|
||||
{
|
||||
result = ProbeResult::BadReturnType;
|
||||
match ocx.sup(cause, self.param_env, return_ty, xform_ret_ty) {
|
||||
Ok(()) => {}
|
||||
Err(_) => {
|
||||
result = ProbeResult::BadReturnType;
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate those obligations to see if they might possibly hold.
|
||||
for error in ocx.select_where_possible() {
|
||||
result = ProbeResult::NoMatch;
|
||||
possibly_unsatisfied_predicates.push((
|
||||
error.obligation.predicate,
|
||||
Some(error.root_obligation.predicate)
|
||||
.filter(|predicate| *predicate != error.obligation.predicate),
|
||||
Some(error.root_obligation.cause),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Previously, method probe used `evaluate_predicate` to determine if a predicate
|
||||
// was impossible to satisfy. This did a leak check, so we must also do a leak
|
||||
// check here to prevent backwards-incompatible ambiguity being introduced. See
|
||||
// `tests/ui/methods/leak-check-disquality.rs` for a simple example of when this
|
||||
// may happen.
|
||||
if let Err(_) = self.leak_check(outer_universe, Some(snapshot)) {
|
||||
result = ProbeResult::NoMatch;
|
||||
}
|
||||
|
||||
result
|
||||
|
@ -1881,12 +1716,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
self.tcx.instantiate_bound_regions_with_erased(xform_fn_sig)
|
||||
}
|
||||
|
||||
/// Gets the type of an impl and generate generic parameters with inference vars.
|
||||
fn impl_ty_and_args(&self, impl_def_id: DefId) -> (Ty<'tcx>, GenericArgsRef<'tcx>) {
|
||||
let args = self.fresh_args_for_item(self.span, impl_def_id);
|
||||
(self.tcx.type_of(impl_def_id).instantiate(self.tcx, args), args)
|
||||
}
|
||||
|
||||
/// Determine if the given associated item type is relevant in the current context.
|
||||
fn is_relevant_kind_for_mode(&self, kind: ty::AssocKind) -> bool {
|
||||
match (self.mode, kind) {
|
||||
|
@ -2008,10 +1837,10 @@ impl<'tcx> Candidate<'tcx> {
|
|||
Pick {
|
||||
item: self.item,
|
||||
kind: match self.kind {
|
||||
InherentImplCandidate(..) => InherentImplPick,
|
||||
ObjectCandidate => ObjectPick,
|
||||
InherentImplCandidate(_) => InherentImplPick,
|
||||
ObjectCandidate(_) => ObjectPick,
|
||||
TraitCandidate(_) => TraitPick,
|
||||
WhereClauseCandidate(ref trait_ref) => {
|
||||
WhereClauseCandidate(trait_ref) => {
|
||||
// Only trait derived from where-clauses should
|
||||
// appear here, so they should not contain any
|
||||
// inference variables or other artifacts. This
|
||||
|
@ -2022,7 +1851,7 @@ impl<'tcx> Candidate<'tcx> {
|
|||
&& !trait_ref.skip_binder().args.has_placeholders()
|
||||
);
|
||||
|
||||
WhereClausePick(*trait_ref)
|
||||
WhereClausePick(trait_ref)
|
||||
}
|
||||
},
|
||||
import_ids: self.import_ids.clone(),
|
||||
|
|
|
@ -129,6 +129,19 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
|||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||
}
|
||||
|
||||
pub fn eq_no_opaques<T: ToTrace<'tcx>>(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
expected: T,
|
||||
actual: T,
|
||||
) -> Result<(), TypeError<'tcx>> {
|
||||
self.infcx
|
||||
.at(cause, param_env)
|
||||
.eq(DefineOpaqueTypes::No, expected, actual)
|
||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||
}
|
||||
|
||||
/// Checks whether `expected` is a subtype of `actual`: `expected <: actual`.
|
||||
pub fn sub<T: ToTrace<'tcx>>(
|
||||
&self,
|
||||
|
|
|
@ -2,15 +2,13 @@ error[E0599]: the method `insert` exists for struct `HashSet<Value>`, but its tr
|
|||
--> $DIR/issue-91550.rs:8:8
|
||||
|
|
||||
LL | struct Value(u32);
|
||||
| ------------ doesn't satisfy `Value: Eq`, `Value: Hash` or `Value: PartialEq`
|
||||
| ------------ doesn't satisfy `Value: Eq` or `Value: Hash`
|
||||
...
|
||||
LL | hs.insert(Value(0));
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`Value: Eq`
|
||||
`Value: PartialEq`
|
||||
which is required by `Value: Eq`
|
||||
`Value: Hash`
|
||||
help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]`
|
||||
|
|
||||
|
@ -22,7 +20,7 @@ error[E0599]: the method `use_eq` exists for struct `Object<NoDerives>`, but its
|
|||
--> $DIR/issue-91550.rs:26:9
|
||||
|
|
||||
LL | pub struct NoDerives;
|
||||
| -------------------- doesn't satisfy `NoDerives: Eq` or `NoDerives: PartialEq`
|
||||
| -------------------- doesn't satisfy `NoDerives: Eq`
|
||||
LL |
|
||||
LL | struct Object<T>(T);
|
||||
| ---------------- method `use_eq` not found for this struct
|
||||
|
@ -37,9 +35,6 @@ LL | impl<T: Eq> Object<T> {
|
|||
| ^^ ---------
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`NoDerives: PartialEq`
|
||||
which is required by `NoDerives: Eq`
|
||||
help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]`
|
||||
|
|
||||
LL + #[derive(Eq, PartialEq)]
|
||||
|
@ -50,7 +45,7 @@ error[E0599]: the method `use_ord` exists for struct `Object<NoDerives>`, but it
|
|||
--> $DIR/issue-91550.rs:27:9
|
||||
|
|
||||
LL | pub struct NoDerives;
|
||||
| -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
|
||||
| -------------------- doesn't satisfy `NoDerives: Ord`
|
||||
LL |
|
||||
LL | struct Object<T>(T);
|
||||
| ---------------- method `use_ord` not found for this struct
|
||||
|
@ -65,13 +60,6 @@ LL | impl<T: Ord> Object<T> {
|
|||
| ^^^ ---------
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`NoDerives: PartialOrd`
|
||||
which is required by `NoDerives: Ord`
|
||||
`NoDerives: PartialEq`
|
||||
which is required by `NoDerives: Ord`
|
||||
`NoDerives: Eq`
|
||||
which is required by `NoDerives: Ord`
|
||||
help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
|
||||
|
|
||||
LL + #[derive(Eq, Ord, PartialEq, PartialOrd)]
|
||||
|
@ -82,7 +70,7 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object<NoD
|
|||
--> $DIR/issue-91550.rs:28:9
|
||||
|
|
||||
LL | pub struct NoDerives;
|
||||
| -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
|
||||
| -------------------- doesn't satisfy `NoDerives: Ord` or `NoDerives: PartialOrd`
|
||||
LL |
|
||||
LL | struct Object<T>(T);
|
||||
| ---------------- method `use_ord_and_partial_ord` not found for this struct
|
||||
|
@ -100,13 +88,6 @@ LL | impl<T: Ord + PartialOrd> Object<T> {
|
|||
| | |
|
||||
| | unsatisfied trait bound introduced here
|
||||
| unsatisfied trait bound introduced here
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`NoDerives: PartialEq`
|
||||
which is required by `NoDerives: Ord`
|
||||
`NoDerives: Eq`
|
||||
which is required by `NoDerives: Ord`
|
||||
`NoDerives: PartialEq`
|
||||
which is required by `NoDerives: PartialOrd`
|
||||
help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
|
||||
|
|
||||
LL + #[derive(Eq, Ord, PartialEq, PartialOrd)]
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::marker::PhantomData;
|
|||
fn _alias_check() {
|
||||
WrongImpl::foo(0i32);
|
||||
//~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||
//~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||
//~| ERROR the function or associated item `foo` exists for struct `SafeImpl<_, RawImpl<_>>`, but its trait bounds were not satisfied
|
||||
WrongImpl::<()>::foo(0i32);
|
||||
//~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied
|
||||
//~| ERROR trait bounds were not satisfied
|
||||
|
|
|
@ -1,30 +1,27 @@
|
|||
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||
--> $DIR/issue-62742.rs:4:5
|
||||
error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<_, RawImpl<_>>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-62742.rs:4:16
|
||||
|
|
||||
LL | WrongImpl::foo(0i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
|
||||
| ^^^ function or associated item cannot be called on `SafeImpl<_, RawImpl<_>>` due to unsatisfied trait bounds
|
||||
...
|
||||
LL | pub struct RawImpl<T>(PhantomData<T>);
|
||||
| --------------------- doesn't satisfy `RawImpl<_>: Raw<_>`
|
||||
...
|
||||
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
|
||||
| ----------------------------------------- function or associated item `foo` not found for this struct
|
||||
|
|
||||
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
|
||||
note: required by a bound in `SafeImpl::<T, A>::foo`
|
||||
note: trait bound `RawImpl<_>: Raw<_>` was not satisfied
|
||||
--> $DIR/issue-62742.rs:29:20
|
||||
|
|
||||
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
|
||||
| ^^^^^^ required by this bound in `SafeImpl::<T, A>::foo`
|
||||
LL | pub fn foo(value: A::Value) {}
|
||||
| --- required by a bound in this associated function
|
||||
|
||||
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||
--> $DIR/issue-62742.rs:4:5
|
||||
| ^^^^^^ --------------
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: the trait `Raw` must be implemented
|
||||
--> $DIR/issue-62742.rs:13:1
|
||||
|
|
||||
LL | WrongImpl::foo(0i32);
|
||||
| ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
|
||||
|
|
||||
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
|
||||
note: required by a bound in `SafeImpl`
|
||||
--> $DIR/issue-62742.rs:27:35
|
||||
|
|
||||
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
|
||||
| ^^^^^^ required by this bound in `SafeImpl`
|
||||
LL | pub trait Raw<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-62742.rs:7:22
|
||||
|
@ -51,6 +48,19 @@ note: the trait `Raw` must be implemented
|
|||
LL | pub trait Raw<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||
--> $DIR/issue-62742.rs:4:5
|
||||
|
|
||||
LL | WrongImpl::foo(0i32);
|
||||
| ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
|
||||
|
|
||||
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
|
||||
note: required by a bound in `SafeImpl`
|
||||
--> $DIR/issue-62742.rs:27:35
|
||||
|
|
||||
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
|
||||
| ^^^^^^ required by this bound in `SafeImpl`
|
||||
|
||||
error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
|
||||
--> $DIR/issue-62742.rs:7:5
|
||||
|
|
||||
|
|
|
@ -29,5 +29,6 @@ where
|
|||
}
|
||||
|
||||
fn main() {
|
||||
Race::new(|race| race.when()); //~ ERROR overflow assigning `_` to `Option<_>`
|
||||
Race::new(|race| race.when());
|
||||
//~^ ERROR the method `when` exists for struct `RaceBuilder<_, Never<_>>`, but its trait bounds were not satisfied
|
||||
}
|
||||
|
|
|
@ -1,9 +1,29 @@
|
|||
error[E0275]: overflow assigning `_` to `Option<_>`
|
||||
--> $DIR/issue-84073.rs:32:22
|
||||
error[E0599]: the method `when` exists for struct `RaceBuilder<_, Never<_>>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-84073.rs:32:27
|
||||
|
|
||||
LL | pub struct Never<T>(PhantomData<T>);
|
||||
| ------------------- doesn't satisfy `Never<_>: StatefulFuture<Option<_>>`
|
||||
...
|
||||
LL | pub struct RaceBuilder<F, S> {
|
||||
| ---------------------------- method `when` not found for this struct
|
||||
...
|
||||
LL | Race::new(|race| race.when());
|
||||
| ^^^^
|
||||
| ^^^^ method cannot be called on `RaceBuilder<_, Never<_>>` due to unsatisfied trait bounds
|
||||
|
|
||||
note: trait bound `Never<_>: StatefulFuture<Option<_>>` was not satisfied
|
||||
--> $DIR/issue-84073.rs:14:8
|
||||
|
|
||||
LL | impl<T, F> RaceBuilder<T, F>
|
||||
| -----------------
|
||||
LL | where
|
||||
LL | F: StatefulFuture<Option<T>>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
|
||||
note: the trait `StatefulFuture` must be implemented
|
||||
--> $DIR/issue-84073.rs:3:1
|
||||
|
|
||||
LL | pub trait StatefulFuture<S> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
For more information about this error, try `rustc --explain E0599`.
|
||||
|
|
|
@ -6,6 +6,7 @@ LL | let _result = &Some(42).as_deref();
|
|||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`{integer}: Deref`
|
||||
which is required by `<{integer} as Deref>::Target = _`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ LL | let _result = &mut Some(42).as_deref_mut();
|
|||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`{integer}: Deref`
|
||||
which is required by `<{integer} as Deref>::Target = _`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ LL | let _result = &Ok(42).as_deref();
|
|||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`{integer}: Deref`
|
||||
which is required by `<{integer} as Deref>::Target = _`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ LL | let _result = &mut Ok(42).as_deref_mut();
|
|||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`{integer}: Deref`
|
||||
which is required by `<{integer} as Deref>::Target = _`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
32
tests/ui/methods/fulfillment-disqualifies-method.rs
Normal file
32
tests/ui/methods/fulfillment-disqualifies-method.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Tests that using fulfillment in the trait solver means that we detect that a
|
||||
// method is impossible, leading to no ambiguity.
|
||||
//@ check-pass
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#[derive(Default)]
|
||||
struct W<A, B>(A, B);
|
||||
|
||||
trait Constrain {
|
||||
type Output;
|
||||
}
|
||||
|
||||
impl Constrain for i32 {
|
||||
type Output = u32;
|
||||
}
|
||||
|
||||
trait Impossible {}
|
||||
|
||||
impl<A, B> W<A, B> where A: Constrain<Output = B>, B: Impossible {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
impl W<i32, u32> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let w: W<i32, _> = W::default();
|
||||
w.method();
|
||||
}
|
26
tests/ui/methods/leak-check-disquality.rs
Normal file
26
tests/ui/methods/leak-check-disquality.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Tests that using fulfillment in the trait solver means that we detect that a
|
||||
// method is impossible, leading to no ambiguity.
|
||||
//@ check-pass
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
struct W<T, U>(Option<T>, Option<U>);
|
||||
|
||||
impl<'a> W<fn(&'a ()), u32> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
trait Leak {}
|
||||
impl<T: Fn(&())> Leak for T {}
|
||||
|
||||
impl<T: Leak> W<T, i32> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
fn test<'a>() {
|
||||
let x: W<fn(&'a ()), _> = W(None, None);
|
||||
x.method();
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -21,14 +21,16 @@ error[E0599]: the method `count` exists for struct `Filter<Fuse<Once<&str>>, {cl
|
|||
LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
|
||||
| --------- ^^^^^ method cannot be called due to unsatisfied trait bounds
|
||||
| |
|
||||
| doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` or `_: FnMut<(&&str,)>`
|
||||
| doesn't satisfy `_: FnMut<(&&str,)>` or `_: FnOnce<(&&str,)>`
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`<{closure@$DIR/issue-36053-2.rs:7:39: 7:48} as FnOnce<(&&str,)>>::Output = bool`
|
||||
which is required by `Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
|
||||
`{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnMut<(&&str,)>`
|
||||
which is required by `Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
|
||||
`Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
|
||||
`{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnOnce<(&&str,)>`
|
||||
which is required by `Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
|
||||
`{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnMut<(&&str,)>`
|
||||
which is required by `&mut Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
|
||||
`{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnOnce<(&&str,)>`
|
||||
which is required by `&mut Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
|
@ -6,8 +6,6 @@ LL | this.is_subset(other)
|
|||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`T: Eq`
|
||||
`T: PartialEq`
|
||||
which is required by `T: Eq`
|
||||
`T: Hash`
|
||||
help: consider restricting the type parameters to satisfy the trait bounds
|
||||
|
|
||||
|
|
|
@ -19,7 +19,8 @@ impl<'a> X for fn(&'a ()) {
|
|||
}
|
||||
|
||||
fn g() {
|
||||
let x = <fn (&())>::make_g(); //~ ERROR the function
|
||||
let x = <fn (&())>::make_g();
|
||||
//~^ ERROR no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
|
||||
error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
|
||||
--> $DIR/issue-57362-2.rs:22:25
|
||||
|
|
||||
LL | let x = <fn (&())>::make_g();
|
||||
| ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
|
||||
| ^^^^^^ function or associated item not found in `fn(&())`
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`for<'a> fn(&'a ()): X`
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `X` defines an item `make_g`, perhaps you need to implement it
|
||||
--> $DIR/issue-57362-2.rs:8:1
|
||||
|
|
|
@ -28,7 +28,8 @@ impl<T> Y for fn(T) {
|
|||
}
|
||||
|
||||
fn higher_ranked_region_has_lost_its_binder() {
|
||||
let x = <fn (&())>::make_g(); //~ ERROR the function
|
||||
let x = <fn (&())>::make_g();
|
||||
//~^ ERROR no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
|
||||
}
|
||||
|
||||
fn magical() {
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
|
||||
error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
|
||||
--> $DIR/issue-57642-higher-ranked-subtype.rs:31:25
|
||||
|
|
||||
LL | let x = <fn (&())>::make_g();
|
||||
| ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
|
||||
| ^^^^^^ function or associated item not found in `fn(&())`
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`for<'a> fn(&'a ()): X`
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `X` defines an item `make_g`, perhaps you need to implement it
|
||||
--> $DIR/issue-57642-higher-ranked-subtype.rs:4:1
|
||||
|
@ -14,7 +12,7 @@ LL | trait X {
|
|||
| ^^^^^^^
|
||||
|
||||
error[E0599]: no function or associated item named `make_f` found for fn pointer `for<'a> fn(&'a ())` in the current scope
|
||||
--> $DIR/issue-57642-higher-ranked-subtype.rs:35:25
|
||||
--> $DIR/issue-57642-higher-ranked-subtype.rs:36:25
|
||||
|
|
||||
LL | let x = <fn (&())>::make_f();
|
||||
| ^^^^^^ function or associated item not found in `fn(&())`
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
//@ check-pass
|
||||
|
||||
// Some trait with a function that returns a slice:
|
||||
pub trait AsSlice {
|
||||
type Element;
|
||||
|
@ -24,6 +22,7 @@ impl<Cont> A<Cont> {
|
|||
Self: AsSlice<Element = Coef>,
|
||||
{
|
||||
self.as_ref_a().as_ref_a();
|
||||
//~^ ERROR no method named `as_ref_a` found for struct `A<&[Coef]>` in the current scope
|
||||
}
|
||||
|
||||
pub fn as_ref_a<Coef>(&self) -> A<&[<Self as AsSlice>::Element]>
|
||||
|
|
17
tests/ui/resolve/issue-85671.stderr
Normal file
17
tests/ui/resolve/issue-85671.stderr
Normal file
|
@ -0,0 +1,17 @@
|
|||
error[E0599]: no method named `as_ref_a` found for struct `A<&[Coef]>` in the current scope
|
||||
--> $DIR/issue-85671.rs:24:25
|
||||
|
|
||||
LL | pub struct A<Cont>(Cont);
|
||||
| ------------------ method `as_ref_a` not found for this struct
|
||||
...
|
||||
LL | self.as_ref_a().as_ref_a();
|
||||
| ---- ^^^^^^^^ method not found in `A<&[Coef]>`
|
||||
| |
|
||||
| method `as_ref_a` is available on `&A<Cont>`
|
||||
|
|
||||
= note: the method was found for
|
||||
- `A<Cont>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
|
@ -74,22 +74,30 @@ LL | struct Struct {
|
|||
error[E0599]: the method `test` exists for struct `Foo<Vec<Enum>, Instant>`, but its trait bounds were not satisfied
|
||||
--> $DIR/derive-trait-for-method-call.rs:40:15
|
||||
|
|
||||
LL | enum Enum {
|
||||
| --------- doesn't satisfy `Enum: Clone`
|
||||
...
|
||||
LL | struct Foo<X, Y> (X, Y);
|
||||
| ---------------- method `test` not found for this struct
|
||||
...
|
||||
LL | let y = x.test();
|
||||
| ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds
|
||||
|
|
||||
note: the following trait bounds were not satisfied:
|
||||
`Instant: Default`
|
||||
`Vec<Enum>: Clone`
|
||||
--> $DIR/derive-trait-for-method-call.rs:20:9
|
||||
note: trait bound `Instant: Default` was not satisfied
|
||||
--> $DIR/derive-trait-for-method-call.rs:20:40
|
||||
|
|
||||
LL | impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
|
||||
| ^^^^^ ^^^^^^^ ---------
|
||||
| | |
|
||||
| | unsatisfied trait bound introduced here
|
||||
| unsatisfied trait bound introduced here
|
||||
| ^^^^^^^ ---------
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`Enum: Clone`
|
||||
which is required by `Vec<Enum>: Clone`
|
||||
help: consider annotating `Enum` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | enum Enum {
|
||||
|
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -12,13 +12,6 @@ note: trait bound `(): Iterator` was not satisfied
|
|||
|
|
||||
LL | trait IteratorAlias = Iterator;
|
||||
| ------------- ^^^^^^^^ unsatisfied trait bound introduced here
|
||||
note: trait bound `(): IteratorAlias` was not satisfied
|
||||
--> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:9:9
|
||||
|
|
||||
LL | impl<I: IteratorAlias> Foo<I> {
|
||||
| ^^^^^^^^^^^^^ ------
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ LL | x.cmp(&x);
|
|||
which is required by `Box<dyn T>: Iterator`
|
||||
`dyn T: Ord`
|
||||
which is required by `Box<dyn T>: Ord`
|
||||
`Box<dyn T>: Iterator`
|
||||
`dyn T: Iterator`
|
||||
which is required by `&mut Box<dyn T>: Iterator`
|
||||
`dyn T: Iterator`
|
||||
which is required by `&mut dyn T: Iterator`
|
||||
|
|
|
@ -2,7 +2,10 @@ error[E0599]: the method `check` exists for struct `Client<()>`, but its trait b
|
|||
--> $DIR/track-obligations.rs:83:16
|
||||
|
|
||||
LL | struct ALayer<C>(C);
|
||||
| ---------------- doesn't satisfy `<_ as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` or `ALayer<()>: ParticularServiceLayer<()>`
|
||||
| ---------------- doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>`
|
||||
...
|
||||
LL | struct AService;
|
||||
| --------------- doesn't satisfy `<AService as Service<Req>>::Response = Res`
|
||||
...
|
||||
LL | struct Client<C>(C);
|
||||
| ---------------- method `check` not found for this struct
|
||||
|
@ -10,27 +13,14 @@ LL | struct Client<C>(C);
|
|||
LL | Client(()).check();
|
||||
| ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds
|
||||
|
|
||||
note: trait bound `<ALayer<()> as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` was not satisfied
|
||||
--> $DIR/track-obligations.rs:35:14
|
||||
note: trait bound `<AService as Service<Req>>::Response = Res` was not satisfied
|
||||
--> $DIR/track-obligations.rs:24:21
|
||||
|
|
||||
LL | pub trait ParticularServiceLayer<C>:
|
||||
| ----------------------
|
||||
LL | Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
|
||||
note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied
|
||||
--> $DIR/track-obligations.rs:71:16
|
||||
|
|
||||
LL | impl<C> Client<C>
|
||||
| ---------
|
||||
LL | impl<T> ParticularService for T
|
||||
| ----------------- -
|
||||
LL | where
|
||||
LL | ALayer<C>: ParticularServiceLayer<C>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
|
||||
note: the trait `ParticularServiceLayer` must be implemented
|
||||
--> $DIR/track-obligations.rs:34:1
|
||||
|
|
||||
LL | / pub trait ParticularServiceLayer<C>:
|
||||
LL | | Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
|
||||
| |____________________________________________________________________^
|
||||
LL | T: Service<Req, Response = Res>,
|
||||
| ^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
|
||||
|
||||
error[E0271]: type mismatch resolving `<AService as Service<Req>>::Response == Res`
|
||||
--> $DIR/track-obligations.rs:87:11
|
||||
|
|
|
@ -39,7 +39,7 @@ LL | | .collect();
|
|||
= note: the following trait bounds were not satisfied:
|
||||
`<TakeWhile<&mut std::vec::IntoIter<u8>, {closure@$DIR/issue-31173.rs:7:21: 7:25}> as Iterator>::Item = &_`
|
||||
which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator`
|
||||
`Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator`
|
||||
`<TakeWhile<&mut std::vec::IntoIter<u8>, {closure@$DIR/issue-31173.rs:7:21: 7:25}> as Iterator>::Item = &_`
|
||||
which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
Loading…
Add table
Reference in a new issue