Auto merge of #43880 - arielb1:noninvasive-probe, r=nikomatsakis
Remove the trait selection impl in method::probe This removes the hacky trait selection reimplementation in `method::probe`, which occasionally comes and causes problems. There are 2 issues I've found with this approach: 1. The older implementation sometimes had a "guess" type from an impl, which allowed subtyping to work. This is why I needed to make a change in `libtest`: there's an `impl<A> Clone for fn(A)` and we're calling `<for<'a> fn(&'a T) as Clone>::clone`. The older implementation would do a subtyping between the impl type and the trait type, so it would do the check for `<fn(A) as Clone>::clone`, and confirmation would continue with the subtyping. The newer implementation directly passes `<for<'a> fn(&'a T) as Clone>::clone` to selection, which fails. I'm not sure how big of a problem that would be in reality, especially after #43690 would remove the `Clone` problem, but I still want a crater run to avoid breaking the world. 2. The older implementation "looked into" impls to display error messages. I'm not sure that's an advantage - it looked exactly 1 level deep. r? @eddyb
This commit is contained in:
commit
b58e31ac03
12 changed files with 461 additions and 691 deletions
|
@ -194,13 +194,12 @@ enum SelectionCandidate<'tcx> {
|
|||
ProjectionCandidate,
|
||||
|
||||
/// Implementation of a `Fn`-family trait by one of the anonymous types
|
||||
/// generated for a `||` expression. The ty::ClosureKind informs the
|
||||
/// confirmation step what ClosureKind obligation to emit.
|
||||
ClosureCandidate(/* closure */ DefId, ty::ClosureSubsts<'tcx>, ty::ClosureKind),
|
||||
/// generated for a `||` expression.
|
||||
ClosureCandidate,
|
||||
|
||||
/// Implementation of a `Generator` trait by one of the anonymous types
|
||||
/// generated for a generator.
|
||||
GeneratorCandidate(/* function / closure */ DefId, ty::ClosureSubsts<'tcx>),
|
||||
GeneratorCandidate,
|
||||
|
||||
/// Implementation of a `Fn`-family trait by one of the anonymous
|
||||
/// types generated for a fn pointer type (e.g., `fn(int)->int`)
|
||||
|
@ -229,20 +228,12 @@ impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> {
|
|||
ObjectCandidate => ObjectCandidate,
|
||||
BuiltinObjectCandidate => BuiltinObjectCandidate,
|
||||
BuiltinUnsizeCandidate => BuiltinUnsizeCandidate,
|
||||
ClosureCandidate => ClosureCandidate,
|
||||
GeneratorCandidate => GeneratorCandidate,
|
||||
|
||||
ParamCandidate(ref trait_ref) => {
|
||||
return tcx.lift(trait_ref).map(ParamCandidate);
|
||||
}
|
||||
GeneratorCandidate(def_id, ref substs) => {
|
||||
return tcx.lift(substs).map(|substs| {
|
||||
GeneratorCandidate(def_id, substs)
|
||||
});
|
||||
}
|
||||
ClosureCandidate(def_id, ref substs, kind) => {
|
||||
return tcx.lift(substs).map(|substs| {
|
||||
ClosureCandidate(def_id, substs, kind)
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1471,23 +1462,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
// touch bound regions, they just capture the in-scope
|
||||
// type/region parameters
|
||||
let self_ty = *obligation.self_ty().skip_binder();
|
||||
let (closure_def_id, substs) = match self_ty.sty {
|
||||
ty::TyGenerator(id, substs, _) => (id, substs),
|
||||
match self_ty.sty {
|
||||
ty::TyGenerator(..) => {
|
||||
debug!("assemble_generator_candidates: self_ty={:?} obligation={:?}",
|
||||
self_ty,
|
||||
obligation);
|
||||
|
||||
candidates.vec.push(GeneratorCandidate);
|
||||
Ok(())
|
||||
}
|
||||
ty::TyInfer(ty::TyVar(_)) => {
|
||||
debug!("assemble_generator_candidates: ambiguous self-type");
|
||||
candidates.ambiguous = true;
|
||||
return Ok(());
|
||||
}
|
||||
_ => { return Ok(()); }
|
||||
};
|
||||
|
||||
debug!("assemble_generator_candidates: self_ty={:?} obligation={:?}",
|
||||
self_ty,
|
||||
obligation);
|
||||
|
||||
candidates.vec.push(GeneratorCandidate(closure_def_id, substs));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Check for the artificial impl that the compiler will create for an obligation like `X :
|
||||
|
@ -1509,36 +1499,31 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
// ok to skip binder because the substs on closure types never
|
||||
// touch bound regions, they just capture the in-scope
|
||||
// type/region parameters
|
||||
let self_ty = *obligation.self_ty().skip_binder();
|
||||
let (closure_def_id, substs) = match self_ty.sty {
|
||||
ty::TyClosure(id, substs) => (id, substs),
|
||||
match obligation.self_ty().skip_binder().sty {
|
||||
ty::TyClosure(closure_def_id, _) => {
|
||||
debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}",
|
||||
kind, obligation);
|
||||
match self.infcx.closure_kind(closure_def_id) {
|
||||
Some(closure_kind) => {
|
||||
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
|
||||
if closure_kind.extends(kind) {
|
||||
candidates.vec.push(ClosureCandidate);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
debug!("assemble_unboxed_candidates: closure_kind not yet known");
|
||||
candidates.vec.push(ClosureCandidate);
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
ty::TyInfer(ty::TyVar(_)) => {
|
||||
debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
|
||||
candidates.ambiguous = true;
|
||||
return Ok(());
|
||||
}
|
||||
_ => { return Ok(()); }
|
||||
};
|
||||
|
||||
debug!("assemble_unboxed_candidates: self_ty={:?} kind={:?} obligation={:?}",
|
||||
self_ty,
|
||||
kind,
|
||||
obligation);
|
||||
|
||||
match self.infcx.closure_kind(closure_def_id) {
|
||||
Some(closure_kind) => {
|
||||
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
|
||||
if closure_kind.extends(kind) {
|
||||
candidates.vec.push(ClosureCandidate(closure_def_id, substs, kind));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
debug!("assemble_unboxed_candidates: closure_kind not yet known");
|
||||
candidates.vec.push(ClosureCandidate(closure_def_id, substs, kind));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Implement one of the `Fn()` family for a fn pointer.
|
||||
|
@ -1855,8 +1840,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
when there are other valid candidates");
|
||||
}
|
||||
ImplCandidate(..) |
|
||||
ClosureCandidate(..) |
|
||||
GeneratorCandidate(..) |
|
||||
ClosureCandidate |
|
||||
GeneratorCandidate |
|
||||
FnPointerCandidate |
|
||||
BuiltinObjectCandidate |
|
||||
BuiltinUnsizeCandidate |
|
||||
|
@ -2198,15 +2183,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
Ok(VtableImpl(self.confirm_impl_candidate(obligation, impl_def_id)))
|
||||
}
|
||||
|
||||
ClosureCandidate(closure_def_id, substs, kind) => {
|
||||
let vtable_closure =
|
||||
self.confirm_closure_candidate(obligation, closure_def_id, substs, kind)?;
|
||||
ClosureCandidate => {
|
||||
let vtable_closure = self.confirm_closure_candidate(obligation)?;
|
||||
Ok(VtableClosure(vtable_closure))
|
||||
}
|
||||
|
||||
GeneratorCandidate(closure_def_id, substs) => {
|
||||
let vtable_generator =
|
||||
self.confirm_generator_candidate(obligation, closure_def_id, substs)?;
|
||||
GeneratorCandidate => {
|
||||
let vtable_generator = self.confirm_generator_candidate(obligation)?;
|
||||
Ok(VtableGenerator(vtable_generator))
|
||||
}
|
||||
|
||||
|
@ -2543,21 +2526,34 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn confirm_generator_candidate(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
substs: ty::ClosureSubsts<'tcx>)
|
||||
-> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
|
||||
obligation: &TraitObligation<'tcx>)
|
||||
-> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
|
||||
SelectionError<'tcx>>
|
||||
{
|
||||
// ok to skip binder because the substs on generator types never
|
||||
// touch bound regions, they just capture the in-scope
|
||||
// type/region parameters
|
||||
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
|
||||
let (closure_def_id, substs) = match self_ty.sty {
|
||||
ty::TyGenerator(id, substs, _) => (id, substs),
|
||||
_ => bug!("closure candidate for non-closure {:?}", obligation)
|
||||
};
|
||||
|
||||
debug!("confirm_generator_candidate({:?},{:?},{:?})",
|
||||
obligation,
|
||||
closure_def_id,
|
||||
substs);
|
||||
|
||||
let trait_ref =
|
||||
self.generator_trait_ref_unnormalized(obligation, closure_def_id, substs);
|
||||
let Normalized {
|
||||
value: trait_ref,
|
||||
obligations
|
||||
} = self.generator_trait_ref(obligation, closure_def_id, substs);
|
||||
} = normalize_with_depth(self,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth+1,
|
||||
&trait_ref);
|
||||
|
||||
debug!("confirm_generator_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
|
||||
closure_def_id,
|
||||
|
@ -2577,22 +2573,36 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn confirm_closure_candidate(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
substs: ty::ClosureSubsts<'tcx>,
|
||||
kind: ty::ClosureKind)
|
||||
obligation: &TraitObligation<'tcx>)
|
||||
-> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>,
|
||||
SelectionError<'tcx>>
|
||||
{
|
||||
debug!("confirm_closure_candidate({:?},{:?},{:?})",
|
||||
obligation,
|
||||
closure_def_id,
|
||||
substs);
|
||||
debug!("confirm_closure_candidate({:?})", obligation);
|
||||
|
||||
let kind = match self.tcx().lang_items.fn_trait_kind(obligation.predicate.0.def_id()) {
|
||||
Some(k) => k,
|
||||
None => bug!("closure candidate for non-fn trait {:?}", obligation)
|
||||
};
|
||||
|
||||
// ok to skip binder because the substs on closure types never
|
||||
// touch bound regions, they just capture the in-scope
|
||||
// type/region parameters
|
||||
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
|
||||
let (closure_def_id, substs) = match self_ty.sty {
|
||||
ty::TyClosure(id, substs) => (id, substs),
|
||||
_ => bug!("closure candidate for non-closure {:?}", obligation)
|
||||
};
|
||||
|
||||
let trait_ref =
|
||||
self.closure_trait_ref_unnormalized(obligation, closure_def_id, substs);
|
||||
let Normalized {
|
||||
value: trait_ref,
|
||||
mut obligations
|
||||
} = self.closure_trait_ref(obligation, closure_def_id, substs);
|
||||
} = normalize_with_depth(self,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth+1,
|
||||
&trait_ref);
|
||||
|
||||
debug!("confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
|
||||
closure_def_id,
|
||||
|
@ -3059,24 +3069,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
ty::Binder(trait_ref)
|
||||
}
|
||||
|
||||
fn closure_trait_ref(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
substs: ty::ClosureSubsts<'tcx>)
|
||||
-> Normalized<'tcx, ty::PolyTraitRef<'tcx>>
|
||||
{
|
||||
let trait_ref = self.closure_trait_ref_unnormalized(
|
||||
obligation, closure_def_id, substs);
|
||||
|
||||
// A closure signature can contain associated types which
|
||||
// must be normalized.
|
||||
normalize_with_depth(self,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth+1,
|
||||
&trait_ref)
|
||||
}
|
||||
|
||||
fn generator_trait_ref_unnormalized(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
|
@ -3098,24 +3090,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
ty::Binder(trait_ref)
|
||||
}
|
||||
|
||||
fn generator_trait_ref(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
substs: ty::ClosureSubsts<'tcx>)
|
||||
-> Normalized<'tcx, ty::PolyTraitRef<'tcx>>
|
||||
{
|
||||
let trait_ref = self.generator_trait_ref_unnormalized(
|
||||
obligation, closure_def_id, substs);
|
||||
|
||||
// A generator signature can contain associated types which
|
||||
// must be normalized.
|
||||
normalize_with_depth(self,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth+1,
|
||||
&trait_ref)
|
||||
}
|
||||
|
||||
/// Returns the obligations that are implied by instantiating an
|
||||
/// impl or trait. The obligations are substituted and fully
|
||||
/// normalized. This is used when confirming an impl or default
|
||||
|
|
|
@ -232,24 +232,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
probe::ExtensionImplPick(impl_def_id) => {
|
||||
// The method being invoked is the method as defined on the trait,
|
||||
// so return the substitutions from the trait. Consider:
|
||||
//
|
||||
// impl<A,B,C> Trait<A,B> for Foo<C> { ... }
|
||||
//
|
||||
// If we instantiate A, B, and C with $A, $B, and $C
|
||||
// respectively, then we want to return the type
|
||||
// parameters from the trait ([$A,$B]), not those from
|
||||
// the impl ([$A,$B,$C]) not the receiver type ([$C]).
|
||||
let impl_polytype = self.impl_self_ty(self.span, impl_def_id);
|
||||
let impl_trait_ref =
|
||||
self.instantiate_type_scheme(self.span,
|
||||
impl_polytype.substs,
|
||||
&self.tcx.impl_trait_ref(impl_def_id).unwrap());
|
||||
impl_trait_ref.substs
|
||||
}
|
||||
|
||||
probe::TraitPick => {
|
||||
let trait_def_id = pick.item.container.id();
|
||||
|
||||
|
|
|
@ -52,10 +52,6 @@ pub enum MethodError<'tcx> {
|
|||
// Multiple methods might apply.
|
||||
Ambiguity(Vec<CandidateSource>),
|
||||
|
||||
// Using a `Fn`/`FnMut`/etc method on a raw closure type before we have inferred its kind.
|
||||
ClosureAmbiguity(// DefId of fn trait
|
||||
DefId),
|
||||
|
||||
// Found an applicable method, but it is not visible. The second argument contains a list of
|
||||
// not-in-scope traits which may work.
|
||||
PrivateMatch(Def, Vec<DefId>),
|
||||
|
@ -63,6 +59,9 @@ pub enum MethodError<'tcx> {
|
|||
// Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
|
||||
// forgotten to import a trait.
|
||||
IllegalSizedBound(Vec<DefId>),
|
||||
|
||||
// Found a match, but the return type is wrong
|
||||
BadReturnType,
|
||||
}
|
||||
|
||||
// Contains a list of static methods that may apply, a list of unsatisfied trait predicates which
|
||||
|
@ -113,9 +112,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
Ok(..) => true,
|
||||
Err(NoMatch(..)) => false,
|
||||
Err(Ambiguity(..)) => true,
|
||||
Err(ClosureAmbiguity(..)) => true,
|
||||
Err(PrivateMatch(..)) => allow_private,
|
||||
Err(IllegalSizedBound(..)) => true,
|
||||
Err(BadReturnType) => {
|
||||
bug!("no return type expectations but got BadReturnType")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -296,22 +296,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
err.emit();
|
||||
}
|
||||
|
||||
MethodError::ClosureAmbiguity(trait_def_id) => {
|
||||
let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \
|
||||
invoked on this closure as we have not yet inferred what \
|
||||
kind of closure it is",
|
||||
item_name,
|
||||
self.tcx.item_path_str(trait_def_id));
|
||||
let msg = if let Some(callee) = rcvr_expr {
|
||||
format!("{}; use overloaded call notation instead (e.g., `{}()`)",
|
||||
msg,
|
||||
self.tcx.hir.node_to_pretty_string(callee.id))
|
||||
} else {
|
||||
msg
|
||||
};
|
||||
self.sess().span_err(span, &msg);
|
||||
}
|
||||
|
||||
MethodError::PrivateMatch(def, out_of_scope_traits) => {
|
||||
let mut err = struct_span_err!(self.tcx.sess, span, E0624,
|
||||
"{} `{}` is private", def.kind_name(), item_name);
|
||||
|
@ -337,6 +321,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
MethodError::BadReturnType => {
|
||||
bug!("no return type expectations but got BadReturnType")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2818,6 +2818,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
formal_ret: Ty<'tcx>,
|
||||
formal_args: &[Ty<'tcx>])
|
||||
-> Vec<Ty<'tcx>> {
|
||||
let formal_ret = self.resolve_type_vars_with_obligations(formal_ret);
|
||||
let expected_args = expected_ret.only_has_type(self).and_then(|ret_ty| {
|
||||
self.fudge_regions_if_ok(&RegionVariableOrigin::Coercion(call_span), || {
|
||||
// Attempt to apply a subtyping relationship between the formal
|
||||
|
@ -3978,6 +3979,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
hir::ExprTup(ref elts) => {
|
||||
let flds = expected.only_has_type(self).and_then(|ty| {
|
||||
let ty = self.resolve_type_vars_with_obligations(ty);
|
||||
match ty.sty {
|
||||
ty::TyTuple(ref flds, _) => Some(&flds[..]),
|
||||
_ => None
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub struct ClientMap;
|
||||
pub struct ClientMap2;
|
||||
|
||||
pub trait Service {
|
||||
type Request;
|
||||
fn call(&self, _req: Self::Request);
|
||||
}
|
||||
|
||||
pub struct S<T>(T);
|
||||
|
||||
impl Service for ClientMap {
|
||||
type Request = S<Box<Fn(i32)>>;
|
||||
fn call(&self, _req: Self::Request) {}
|
||||
}
|
||||
|
||||
|
||||
impl Service for ClientMap2 {
|
||||
type Request = (Box<Fn(i32)>,);
|
||||
fn call(&self, _req: Self::Request) {}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
ClientMap.call(S { 0: Box::new(|_msgid| ()) });
|
||||
ClientMap.call(S(Box::new(|_msgid| ())));
|
||||
ClientMap2.call((Box::new(|_msgid| ()),));
|
||||
}
|
|
@ -8,8 +8,10 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(fn_traits)]
|
||||
|
||||
fn main() {
|
||||
let mut zero = || {};
|
||||
let () = zero.call_mut(());
|
||||
//~^ ERROR we have not yet inferred what kind of closure it is
|
||||
let mut zero = || 0;
|
||||
let x = zero.call_mut(());
|
||||
assert_eq!(x, 0);
|
||||
}
|
|
@ -8,6 +8,8 @@ error[E0599]: no method named `method` found for type `u32` in the current scope
|
|||
= note: the following traits are implemented but not in scope, perhaps add a `use` for one of them:
|
||||
candidate #1: `use foo::Bar;`
|
||||
candidate #2: `use no_method_suggested_traits::foo::PubPub;`
|
||||
candidate #3: `use no_method_suggested_traits::qux::PrivPub;`
|
||||
candidate #4: `use no_method_suggested_traits::Reexported;`
|
||||
|
||||
error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&u32>>` in the current scope
|
||||
--> $DIR/no-method-suggested-traits.rs:38:44
|
||||
|
@ -19,6 +21,8 @@ error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::box
|
|||
= note: the following traits are implemented but not in scope, perhaps add a `use` for one of them:
|
||||
candidate #1: `use foo::Bar;`
|
||||
candidate #2: `use no_method_suggested_traits::foo::PubPub;`
|
||||
candidate #3: `use no_method_suggested_traits::qux::PrivPub;`
|
||||
candidate #4: `use no_method_suggested_traits::Reexported;`
|
||||
|
||||
error[E0599]: no method named `method` found for type `char` in the current scope
|
||||
--> $DIR/no-method-suggested-traits.rs:44:9
|
||||
|
|
|
@ -5,8 +5,8 @@ error[E0599]: no method named `count` found for type `std::iter::Filter<std::ite
|
|||
| ^^^^^
|
||||
|
|
||||
= note: the method `count` exists but the following trait bounds were not satisfied:
|
||||
`[closure@$DIR/issue-36053-2.rs:17:39: 17:53] : std::ops::FnMut<(&_,)>`
|
||||
`std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
|
||||
`&mut std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
|
||||
|
||||
error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` implements the trait `for<'r> std::ops::FnMut<(&'r str,)>`, but the trait `for<'r> std::ops::FnMut<(&'r &str,)>` is required
|
||||
--> $DIR/issue-36053-2.rs:17:32
|
||||
|
|
19
src/test/ui/suggestions/issue-43420-no-over-suggest.rs
Normal file
19
src/test/ui/suggestions/issue-43420-no-over-suggest.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// check that we substitute type parameters before we suggest anything - otherwise
|
||||
// we would suggest function such as `as_slice` for the `&[u16]`.
|
||||
|
||||
fn foo(b: &[u16]) {}
|
||||
|
||||
fn main() {
|
||||
let a: Vec<u8> = Vec::new();
|
||||
foo(&a);
|
||||
}
|
11
src/test/ui/suggestions/issue-43420-no-over-suggest.stderr
Normal file
11
src/test/ui/suggestions/issue-43420-no-over-suggest.stderr
Normal file
|
@ -0,0 +1,11 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-43420-no-over-suggest.rs:18:9
|
||||
|
|
||||
18 | foo(&a);
|
||||
| ^^ expected slice, found struct `std::vec::Vec`
|
||||
|
|
||||
= note: expected type `&[u16]`
|
||||
found type `&std::vec::Vec<u8>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue