Skip to content

Commit 819d395

Browse files
committed
Properly deal with GATs when looking for method chains to point at
1 parent 5257aee commit 819d395

File tree

4 files changed

+58
-9
lines changed

4 files changed

+58
-9
lines changed

compiler/rustc_trait_selection/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#![allow(internal_features)]
1717
#![allow(rustc::diagnostic_outside_of_impl)]
1818
#![allow(rustc::untranslatable_diagnostic)]
19+
#![feature(assert_matches)]
1920
#![feature(associated_type_bounds)]
2021
#![feature(box_patterns)]
2122
#![feature(control_flow_enum)]

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use rustc_span::def_id::LocalDefId;
3838
use rustc_span::symbol::{kw, sym, Ident, Symbol};
3939
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
4040
use rustc_target::spec::abi;
41+
use std::assert_matches::debug_assert_matches;
4142
use std::borrow::Cow;
4243
use std::iter;
4344

@@ -4219,18 +4220,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
42194220
};
42204221

42214222
let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
4222-
let trait_def_id = proj.trait_def_id(self.tcx);
42234223
// Make `Self` be equivalent to the type of the call chain
42244224
// expression we're looking at now, so that we can tell what
42254225
// for example `Iterator::Item` is at this point in the chain.
4226-
let args = GenericArgs::for_item(self.tcx, trait_def_id, |param, _| {
4227-
match param.kind {
4228-
ty::GenericParamDefKind::Type { .. } => {
4229-
if param.index == 0 {
4230-
return prev_ty.into();
4231-
}
4232-
}
4233-
ty::GenericParamDefKind::Lifetime | ty::GenericParamDefKind::Const { .. } => {}
4226+
let args = GenericArgs::for_item(self.tcx, proj.def_id, |param, _| {
4227+
if param.index == 0 {
4228+
debug_assert_matches!(param.kind, ty::GenericParamDefKind::Type { .. });
4229+
return prev_ty.into();
42344230
}
42354231
self.var_for_def(span, param)
42364232
});

tests/ui/typeck/method-chain-gats.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Regression test for issue #121898.
2+
3+
trait Base {
4+
type Base<B>;
5+
}
6+
7+
trait Functor<A>: Base {
8+
fn fmap<B>(self, f: impl Fn(A) -> B) -> Self::Base<B>
9+
where
10+
Self::Base<B>: Functor<B>;
11+
}
12+
13+
fn fmap2<T, A, B, C>(input: T, f1: impl Fn(A) -> B, f2: impl Fn(B) -> C) -> T::Base<C>
14+
where
15+
T: Functor<A>,
16+
T::Base<B>: Functor<B, Base<C> = T::Base<C>>,
17+
{
18+
input.fmap(f1).fmap(f2)
19+
//~^ ERROR the trait bound `<T as Base>::Base<C>: Functor<C>` is not satisfied
20+
}
21+
22+
fn main() {}
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error[E0277]: the trait bound `<T as Base>::Base<C>: Functor<C>` is not satisfied
2+
--> $DIR/method-chain-gats.rs:18:20
3+
|
4+
LL | input.fmap(f1).fmap(f2)
5+
| ^^^^ the trait `Functor<C>` is not implemented for `<T as Base>::Base<C>`
6+
|
7+
note: the method call chain might not have had the expected associated types
8+
--> $DIR/method-chain-gats.rs:13:29
9+
|
10+
LL | fn fmap2<T, A, B, C>(input: T, f1: impl Fn(A) -> B, f2: impl Fn(B) -> C) -> T::Base<C>
11+
| ^ `Base::Base` is `<T as Base>::Base<_>` here
12+
...
13+
LL | input.fmap(f1).fmap(f2)
14+
| -------- `Base::Base` remains `_` here
15+
note: required by a bound in `Functor::fmap`
16+
--> $DIR/method-chain-gats.rs:10:24
17+
|
18+
LL | fn fmap<B>(self, f: impl Fn(A) -> B) -> Self::Base<B>
19+
| ---- required by a bound in this associated function
20+
LL | where
21+
LL | Self::Base<B>: Functor<B>;
22+
| ^^^^^^^^^^ required by this bound in `Functor::fmap`
23+
help: consider further restricting the associated type
24+
|
25+
LL | T::Base<B>: Functor<B, Base<C> = T::Base<C>>, <T as Base>::Base<C>: Functor<C>
26+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27+
28+
error: aborting due to 1 previous error
29+
30+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)