Skip to content

Commit 34425c8

Browse files
authored
Rollup merge of #104258 - compiler-errors:tait-closure-deduce, r=oli-obk
Deduce closure signature from a type alias `impl Trait`'s supertraits r? `@oli-obk` Basically pass the TAIT's bounds through the same method that we're using to deduce a signature from infer var closure bounds. Does this need a new FCP? I see it as a logical extension of #101834, but happy to rfcbot a new one if it does.
2 parents add6f14 + 9c8037c commit 34425c8

File tree

3 files changed

+94
-42
lines changed

3 files changed

+94
-42
lines changed

compiler/rustc_hir_typeck/src/closure.rs

+10-33
Original file line numberDiff line numberDiff line change
@@ -173,34 +173,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
173173
expected_ty: Ty<'tcx>,
174174
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
175175
match *expected_ty.kind() {
176-
ty::Opaque(def_id, substs) => {
177-
let bounds = self.tcx.bound_explicit_item_bounds(def_id);
178-
let sig =
179-
bounds.subst_iter_copied(self.tcx, substs).find_map(|(pred, span)| match pred
180-
.kind()
181-
.skip_binder()
182-
{
183-
ty::PredicateKind::Projection(proj_predicate) => self
184-
.deduce_sig_from_projection(
185-
Some(span),
186-
pred.kind().rebind(proj_predicate),
187-
),
188-
_ => None,
189-
});
190-
191-
let kind = bounds
192-
.0
193-
.iter()
194-
.filter_map(|(pred, _)| match pred.kind().skip_binder() {
195-
ty::PredicateKind::Trait(tp) => {
196-
self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
197-
}
198-
_ => None,
199-
})
200-
.fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
201-
trace!(?sig, ?kind);
202-
(sig, kind)
203-
}
176+
ty::Opaque(def_id, substs) => self.deduce_signature_from_predicates(
177+
self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
178+
),
204179
ty::Dynamic(ref object_type, ..) => {
205180
let sig = object_type.projection_bounds().find_map(|pb| {
206181
let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
@@ -211,7 +186,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
211186
.and_then(|did| self.tcx.fn_trait_kind_from_lang_item(did));
212187
(sig, kind)
213188
}
214-
ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
189+
ty::Infer(ty::TyVar(vid)) => self.deduce_signature_from_predicates(
190+
self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)),
191+
),
215192
ty::FnPtr(sig) => {
216193
let expected_sig = ExpectedSig { cause_span: None, sig };
217194
(Some(expected_sig), Some(ty::ClosureKind::Fn))
@@ -220,19 +197,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
220197
}
221198
}
222199

223-
fn deduce_expectations_from_obligations(
200+
fn deduce_signature_from_predicates(
224201
&self,
225-
expected_vid: ty::TyVid,
202+
predicates: impl DoubleEndedIterator<Item = (ty::Predicate<'tcx>, Span)>,
226203
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
227204
let mut expected_sig = None;
228205
let mut expected_kind = None;
229206

230-
for obligation in traits::elaborate_obligations(
207+
for obligation in traits::elaborate_predicates_with_span(
231208
self.tcx,
232209
// Reverse the obligations here, since `elaborate_*` uses a stack,
233210
// and we want to keep inference generally in the same order of
234211
// the registered obligations.
235-
self.obligations_for_self_ty(expected_vid).rev().collect(),
212+
predicates.rev(),
236213
) {
237214
debug!(?obligation.predicate);
238215
let bound_predicate = obligation.predicate.kind();

compiler/rustc_middle/src/ty/subst.rs

+69-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
66
use crate::ty::visit::{TypeVisitable, TypeVisitor};
77
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
88

9-
use rustc_data_structures::captures::Captures;
109
use rustc_data_structures::intern::{Interned, WithStableHash};
1110
use rustc_hir::def_id::DefId;
1211
use rustc_macros::HashStable;
@@ -19,7 +18,7 @@ use std::fmt;
1918
use std::marker::PhantomData;
2019
use std::mem;
2120
use std::num::NonZeroUsize;
22-
use std::ops::ControlFlow;
21+
use std::ops::{ControlFlow, Deref};
2322
use std::slice;
2423

2524
/// An entity in the Rust type system, which can be one of
@@ -562,25 +561,86 @@ impl<T, U> EarlyBinder<(T, U)> {
562561
}
563562
}
564563

565-
impl<'tcx, 's, T: IntoIterator<Item = I>, I: TypeFoldable<'tcx>> EarlyBinder<T> {
564+
impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
565+
where
566+
I::Item: TypeFoldable<'tcx>,
567+
{
566568
pub fn subst_iter(
567569
self,
568570
tcx: TyCtxt<'tcx>,
569571
substs: &'s [GenericArg<'tcx>],
570-
) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> {
571-
self.0.into_iter().map(move |t| EarlyBinder(t).subst(tcx, substs))
572+
) -> SubstIter<'s, 'tcx, I> {
573+
SubstIter { it: self.0.into_iter(), tcx, substs }
574+
}
575+
}
576+
577+
pub struct SubstIter<'s, 'tcx, I: IntoIterator> {
578+
it: I::IntoIter,
579+
tcx: TyCtxt<'tcx>,
580+
substs: &'s [GenericArg<'tcx>],
581+
}
582+
583+
impl<'tcx, I: IntoIterator> Iterator for SubstIter<'_, 'tcx, I>
584+
where
585+
I::Item: TypeFoldable<'tcx>,
586+
{
587+
type Item = I::Item;
588+
589+
fn next(&mut self) -> Option<Self::Item> {
590+
Some(EarlyBinder(self.it.next()?).subst(self.tcx, self.substs))
591+
}
592+
}
593+
594+
impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIter<'_, 'tcx, I>
595+
where
596+
I::IntoIter: DoubleEndedIterator,
597+
I::Item: TypeFoldable<'tcx>,
598+
{
599+
fn next_back(&mut self) -> Option<Self::Item> {
600+
Some(EarlyBinder(self.it.next_back()?).subst(self.tcx, self.substs))
572601
}
573602
}
574603

575-
impl<'tcx, 's, 'a, T: IntoIterator<Item = &'a I>, I: Copy + TypeFoldable<'tcx> + 'a>
576-
EarlyBinder<T>
604+
impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
605+
where
606+
I::Item: Deref,
607+
<I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
577608
{
578609
pub fn subst_iter_copied(
579610
self,
580611
tcx: TyCtxt<'tcx>,
581612
substs: &'s [GenericArg<'tcx>],
582-
) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> + Captures<'a> {
583-
self.0.into_iter().map(move |t| EarlyBinder(*t).subst(tcx, substs))
613+
) -> SubstIterCopied<'s, 'tcx, I> {
614+
SubstIterCopied { it: self.0.into_iter(), tcx, substs }
615+
}
616+
}
617+
618+
pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> {
619+
it: I::IntoIter,
620+
tcx: TyCtxt<'tcx>,
621+
substs: &'a [GenericArg<'tcx>],
622+
}
623+
624+
impl<'tcx, I: IntoIterator> Iterator for SubstIterCopied<'_, 'tcx, I>
625+
where
626+
I::Item: Deref,
627+
<I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
628+
{
629+
type Item = <I::Item as Deref>::Target;
630+
631+
fn next(&mut self) -> Option<Self::Item> {
632+
Some(EarlyBinder(*self.it.next()?).subst(self.tcx, self.substs))
633+
}
634+
}
635+
636+
impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIterCopied<'_, 'tcx, I>
637+
where
638+
I::IntoIter: DoubleEndedIterator,
639+
I::Item: Deref,
640+
<I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
641+
{
642+
fn next_back(&mut self) -> Option<Self::Item> {
643+
Some(EarlyBinder(*self.it.next_back()?).subst(self.tcx, self.substs))
584644
}
585645
}
586646

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// check-pass
2+
3+
#![feature(type_alias_impl_trait)]
4+
5+
trait SuperExpectation: Fn(i32) {}
6+
7+
impl<T: Fn(i32)> SuperExpectation for T {}
8+
9+
type Foo = impl SuperExpectation;
10+
11+
fn main() {
12+
let _: Foo = |x| {
13+
let _ = x.to_string();
14+
};
15+
}

0 commit comments

Comments
 (0)