Skip to content

Commit b58e31a

Browse files
committed
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
2 parents c2f9cc4 + 15f6540 commit b58e31a

12 files changed

+463
-693
lines changed

src/librustc/traits/select.rs

+80-106
Original file line numberDiff line numberDiff line change
@@ -194,13 +194,12 @@ enum SelectionCandidate<'tcx> {
194194
ProjectionCandidate,
195195

196196
/// Implementation of a `Fn`-family trait by one of the anonymous types
197-
/// generated for a `||` expression. The ty::ClosureKind informs the
198-
/// confirmation step what ClosureKind obligation to emit.
199-
ClosureCandidate(/* closure */ DefId, ty::ClosureSubsts<'tcx>, ty::ClosureKind),
197+
/// generated for a `||` expression.
198+
ClosureCandidate,
200199

201200
/// Implementation of a `Generator` trait by one of the anonymous types
202201
/// generated for a generator.
203-
GeneratorCandidate(/* function / closure */ DefId, ty::ClosureSubsts<'tcx>),
202+
GeneratorCandidate,
204203

205204
/// Implementation of a `Fn`-family trait by one of the anonymous
206205
/// 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> {
229228
ObjectCandidate => ObjectCandidate,
230229
BuiltinObjectCandidate => BuiltinObjectCandidate,
231230
BuiltinUnsizeCandidate => BuiltinUnsizeCandidate,
231+
ClosureCandidate => ClosureCandidate,
232+
GeneratorCandidate => GeneratorCandidate,
232233

233234
ParamCandidate(ref trait_ref) => {
234235
return tcx.lift(trait_ref).map(ParamCandidate);
235236
}
236-
GeneratorCandidate(def_id, ref substs) => {
237-
return tcx.lift(substs).map(|substs| {
238-
GeneratorCandidate(def_id, substs)
239-
});
240-
}
241-
ClosureCandidate(def_id, ref substs, kind) => {
242-
return tcx.lift(substs).map(|substs| {
243-
ClosureCandidate(def_id, substs, kind)
244-
});
245-
}
246237
})
247238
}
248239
}
@@ -1471,23 +1462,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
14711462
// touch bound regions, they just capture the in-scope
14721463
// type/region parameters
14731464
let self_ty = *obligation.self_ty().skip_binder();
1474-
let (closure_def_id, substs) = match self_ty.sty {
1475-
ty::TyGenerator(id, substs, _) => (id, substs),
1465+
match self_ty.sty {
1466+
ty::TyGenerator(..) => {
1467+
debug!("assemble_generator_candidates: self_ty={:?} obligation={:?}",
1468+
self_ty,
1469+
obligation);
1470+
1471+
candidates.vec.push(GeneratorCandidate);
1472+
Ok(())
1473+
}
14761474
ty::TyInfer(ty::TyVar(_)) => {
14771475
debug!("assemble_generator_candidates: ambiguous self-type");
14781476
candidates.ambiguous = true;
14791477
return Ok(());
14801478
}
14811479
_ => { return Ok(()); }
1482-
};
1483-
1484-
debug!("assemble_generator_candidates: self_ty={:?} obligation={:?}",
1485-
self_ty,
1486-
obligation);
1487-
1488-
candidates.vec.push(GeneratorCandidate(closure_def_id, substs));
1489-
1490-
Ok(())
1480+
}
14911481
}
14921482

14931483
/// 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> {
15091499
// ok to skip binder because the substs on closure types never
15101500
// touch bound regions, they just capture the in-scope
15111501
// type/region parameters
1512-
let self_ty = *obligation.self_ty().skip_binder();
1513-
let (closure_def_id, substs) = match self_ty.sty {
1514-
ty::TyClosure(id, substs) => (id, substs),
1502+
match obligation.self_ty().skip_binder().sty {
1503+
ty::TyClosure(closure_def_id, _) => {
1504+
debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}",
1505+
kind, obligation);
1506+
match self.infcx.closure_kind(closure_def_id) {
1507+
Some(closure_kind) => {
1508+
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
1509+
if closure_kind.extends(kind) {
1510+
candidates.vec.push(ClosureCandidate);
1511+
}
1512+
}
1513+
None => {
1514+
debug!("assemble_unboxed_candidates: closure_kind not yet known");
1515+
candidates.vec.push(ClosureCandidate);
1516+
}
1517+
};
1518+
Ok(())
1519+
}
15151520
ty::TyInfer(ty::TyVar(_)) => {
15161521
debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
15171522
candidates.ambiguous = true;
15181523
return Ok(());
15191524
}
15201525
_ => { return Ok(()); }
1521-
};
1522-
1523-
debug!("assemble_unboxed_candidates: self_ty={:?} kind={:?} obligation={:?}",
1524-
self_ty,
1525-
kind,
1526-
obligation);
1527-
1528-
match self.infcx.closure_kind(closure_def_id) {
1529-
Some(closure_kind) => {
1530-
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
1531-
if closure_kind.extends(kind) {
1532-
candidates.vec.push(ClosureCandidate(closure_def_id, substs, kind));
1533-
}
1534-
}
1535-
None => {
1536-
debug!("assemble_unboxed_candidates: closure_kind not yet known");
1537-
candidates.vec.push(ClosureCandidate(closure_def_id, substs, kind));
1538-
}
15391526
}
1540-
1541-
Ok(())
15421527
}
15431528

15441529
/// Implement one of the `Fn()` family for a fn pointer.
@@ -1855,8 +1840,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
18551840
when there are other valid candidates");
18561841
}
18571842
ImplCandidate(..) |
1858-
ClosureCandidate(..) |
1859-
GeneratorCandidate(..) |
1843+
ClosureCandidate |
1844+
GeneratorCandidate |
18601845
FnPointerCandidate |
18611846
BuiltinObjectCandidate |
18621847
BuiltinUnsizeCandidate |
@@ -2198,15 +2183,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
21982183
Ok(VtableImpl(self.confirm_impl_candidate(obligation, impl_def_id)))
21992184
}
22002185

2201-
ClosureCandidate(closure_def_id, substs, kind) => {
2202-
let vtable_closure =
2203-
self.confirm_closure_candidate(obligation, closure_def_id, substs, kind)?;
2186+
ClosureCandidate => {
2187+
let vtable_closure = self.confirm_closure_candidate(obligation)?;
22042188
Ok(VtableClosure(vtable_closure))
22052189
}
22062190

2207-
GeneratorCandidate(closure_def_id, substs) => {
2208-
let vtable_generator =
2209-
self.confirm_generator_candidate(obligation, closure_def_id, substs)?;
2191+
GeneratorCandidate => {
2192+
let vtable_generator = self.confirm_generator_candidate(obligation)?;
22102193
Ok(VtableGenerator(vtable_generator))
22112194
}
22122195

@@ -2543,21 +2526,34 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
25432526
}
25442527

25452528
fn confirm_generator_candidate(&mut self,
2546-
obligation: &TraitObligation<'tcx>,
2547-
closure_def_id: DefId,
2548-
substs: ty::ClosureSubsts<'tcx>)
2549-
-> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
2529+
obligation: &TraitObligation<'tcx>)
2530+
-> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
25502531
SelectionError<'tcx>>
25512532
{
2533+
// ok to skip binder because the substs on generator types never
2534+
// touch bound regions, they just capture the in-scope
2535+
// type/region parameters
2536+
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
2537+
let (closure_def_id, substs) = match self_ty.sty {
2538+
ty::TyGenerator(id, substs, _) => (id, substs),
2539+
_ => bug!("closure candidate for non-closure {:?}", obligation)
2540+
};
2541+
25522542
debug!("confirm_generator_candidate({:?},{:?},{:?})",
25532543
obligation,
25542544
closure_def_id,
25552545
substs);
25562546

2547+
let trait_ref =
2548+
self.generator_trait_ref_unnormalized(obligation, closure_def_id, substs);
25572549
let Normalized {
25582550
value: trait_ref,
25592551
obligations
2560-
} = self.generator_trait_ref(obligation, closure_def_id, substs);
2552+
} = normalize_with_depth(self,
2553+
obligation.param_env,
2554+
obligation.cause.clone(),
2555+
obligation.recursion_depth+1,
2556+
&trait_ref);
25612557

25622558
debug!("confirm_generator_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
25632559
closure_def_id,
@@ -2577,22 +2573,36 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
25772573
}
25782574

25792575
fn confirm_closure_candidate(&mut self,
2580-
obligation: &TraitObligation<'tcx>,
2581-
closure_def_id: DefId,
2582-
substs: ty::ClosureSubsts<'tcx>,
2583-
kind: ty::ClosureKind)
2576+
obligation: &TraitObligation<'tcx>)
25842577
-> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>,
25852578
SelectionError<'tcx>>
25862579
{
2587-
debug!("confirm_closure_candidate({:?},{:?},{:?})",
2588-
obligation,
2589-
closure_def_id,
2590-
substs);
2580+
debug!("confirm_closure_candidate({:?})", obligation);
2581+
2582+
let kind = match self.tcx().lang_items.fn_trait_kind(obligation.predicate.0.def_id()) {
2583+
Some(k) => k,
2584+
None => bug!("closure candidate for non-fn trait {:?}", obligation)
2585+
};
2586+
2587+
// ok to skip binder because the substs on closure types never
2588+
// touch bound regions, they just capture the in-scope
2589+
// type/region parameters
2590+
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
2591+
let (closure_def_id, substs) = match self_ty.sty {
2592+
ty::TyClosure(id, substs) => (id, substs),
2593+
_ => bug!("closure candidate for non-closure {:?}", obligation)
2594+
};
25912595

2596+
let trait_ref =
2597+
self.closure_trait_ref_unnormalized(obligation, closure_def_id, substs);
25922598
let Normalized {
25932599
value: trait_ref,
25942600
mut obligations
2595-
} = self.closure_trait_ref(obligation, closure_def_id, substs);
2601+
} = normalize_with_depth(self,
2602+
obligation.param_env,
2603+
obligation.cause.clone(),
2604+
obligation.recursion_depth+1,
2605+
&trait_ref);
25962606

25972607
debug!("confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
25982608
closure_def_id,
@@ -3059,24 +3069,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
30593069
ty::Binder(trait_ref)
30603070
}
30613071

3062-
fn closure_trait_ref(&mut self,
3063-
obligation: &TraitObligation<'tcx>,
3064-
closure_def_id: DefId,
3065-
substs: ty::ClosureSubsts<'tcx>)
3066-
-> Normalized<'tcx, ty::PolyTraitRef<'tcx>>
3067-
{
3068-
let trait_ref = self.closure_trait_ref_unnormalized(
3069-
obligation, closure_def_id, substs);
3070-
3071-
// A closure signature can contain associated types which
3072-
// must be normalized.
3073-
normalize_with_depth(self,
3074-
obligation.param_env,
3075-
obligation.cause.clone(),
3076-
obligation.recursion_depth+1,
3077-
&trait_ref)
3078-
}
3079-
30803072
fn generator_trait_ref_unnormalized(&mut self,
30813073
obligation: &TraitObligation<'tcx>,
30823074
closure_def_id: DefId,
@@ -3098,24 +3090,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
30983090
ty::Binder(trait_ref)
30993091
}
31003092

3101-
fn generator_trait_ref(&mut self,
3102-
obligation: &TraitObligation<'tcx>,
3103-
closure_def_id: DefId,
3104-
substs: ty::ClosureSubsts<'tcx>)
3105-
-> Normalized<'tcx, ty::PolyTraitRef<'tcx>>
3106-
{
3107-
let trait_ref = self.generator_trait_ref_unnormalized(
3108-
obligation, closure_def_id, substs);
3109-
3110-
// A generator signature can contain associated types which
3111-
// must be normalized.
3112-
normalize_with_depth(self,
3113-
obligation.param_env,
3114-
obligation.cause.clone(),
3115-
obligation.recursion_depth+1,
3116-
&trait_ref)
3117-
}
3118-
31193093
/// Returns the obligations that are implied by instantiating an
31203094
/// impl or trait. The obligations are substituted and fully
31213095
/// normalized. This is used when confirming an impl or default

src/librustc_typeck/check/method/confirm.rs

-18
Original file line numberDiff line numberDiff line change
@@ -232,24 +232,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
232232
})
233233
}
234234

235-
probe::ExtensionImplPick(impl_def_id) => {
236-
// The method being invoked is the method as defined on the trait,
237-
// so return the substitutions from the trait. Consider:
238-
//
239-
// impl<A,B,C> Trait<A,B> for Foo<C> { ... }
240-
//
241-
// If we instantiate A, B, and C with $A, $B, and $C
242-
// respectively, then we want to return the type
243-
// parameters from the trait ([$A,$B]), not those from
244-
// the impl ([$A,$B,$C]) not the receiver type ([$C]).
245-
let impl_polytype = self.impl_self_ty(self.span, impl_def_id);
246-
let impl_trait_ref =
247-
self.instantiate_type_scheme(self.span,
248-
impl_polytype.substs,
249-
&self.tcx.impl_trait_ref(impl_def_id).unwrap());
250-
impl_trait_ref.substs
251-
}
252-
253235
probe::TraitPick => {
254236
let trait_def_id = pick.item.container.id();
255237

src/librustc_typeck/check/method/mod.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,16 @@ pub enum MethodError<'tcx> {
5252
// Multiple methods might apply.
5353
Ambiguity(Vec<CandidateSource>),
5454

55-
// Using a `Fn`/`FnMut`/etc method on a raw closure type before we have inferred its kind.
56-
ClosureAmbiguity(// DefId of fn trait
57-
DefId),
58-
5955
// Found an applicable method, but it is not visible. The second argument contains a list of
6056
// not-in-scope traits which may work.
6157
PrivateMatch(Def, Vec<DefId>),
6258

6359
// Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
6460
// forgotten to import a trait.
6561
IllegalSizedBound(Vec<DefId>),
62+
63+
// Found a match, but the return type is wrong
64+
BadReturnType,
6665
}
6766

6867
// 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> {
113112
Ok(..) => true,
114113
Err(NoMatch(..)) => false,
115114
Err(Ambiguity(..)) => true,
116-
Err(ClosureAmbiguity(..)) => true,
117115
Err(PrivateMatch(..)) => allow_private,
118116
Err(IllegalSizedBound(..)) => true,
117+
Err(BadReturnType) => {
118+
bug!("no return type expectations but got BadReturnType")
119+
}
120+
119121
}
120122
}
121123

0 commit comments

Comments
 (0)