Rollup merge of #105846 - compiler-errors:issue-105838, r=jackh726
Account for return-position `impl Trait` in trait in `opt_suggest_box_span` RPITITs are the only types where their opaque bounds might normalize to some other self type than the opaque type itself. To avoid needing to do normalization, let's just match on either alias kind. Ideally, we'd just get rid of `opt_suggest_box_span`. It's kind of a wart on type-checking `if`/`match`. I've recently refactored this expression for being confusing/wrong, but moving it into the error path is pretty hard. Fixes #105838
This commit is contained in:
commit
f9ccbf084f
@ -526,7 +526,6 @@ pub(crate) fn opt_suggest_box_span(
|
||||
None
|
||||
}
|
||||
})?;
|
||||
let opaque_ty = self.tcx.mk_opaque(rpit_def_id, substs);
|
||||
|
||||
if !self.can_coerce(first_ty, expected) || !self.can_coerce(second_ty, expected) {
|
||||
return None;
|
||||
@ -540,13 +539,22 @@ pub(crate) fn opt_suggest_box_span(
|
||||
{
|
||||
let pred = pred.kind().rebind(match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => {
|
||||
assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
|
||||
// FIXME(rpitit): This will need to be fixed when we move to associated types
|
||||
assert!(matches!(
|
||||
*trait_pred.trait_ref.self_ty().kind(),
|
||||
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
|
||||
if def_id == rpit_def_id && substs == substs
|
||||
));
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(
|
||||
trait_pred.with_self_ty(self.tcx, ty),
|
||||
))
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(mut proj_pred)) => {
|
||||
assert_eq!(proj_pred.projection_ty.self_ty(), opaque_ty);
|
||||
assert!(matches!(
|
||||
*proj_pred.projection_ty.self_ty().kind(),
|
||||
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
|
||||
if def_id == rpit_def_id && substs == substs
|
||||
));
|
||||
proj_pred = proj_pred.with_self_ty(self.tcx, ty);
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(proj_pred))
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(return_position_impl_trait_in_trait)]
|
||||
//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete
|
||||
|
||||
struct TestA {}
|
||||
struct TestB {}
|
||||
|
||||
impl TestTrait for TestA {
|
||||
type Output = ();
|
||||
}
|
||||
impl TestTrait for TestB {
|
||||
type Output = ();
|
||||
}
|
||||
|
||||
trait TestTrait {
|
||||
type Output;
|
||||
}
|
||||
|
||||
impl<A, B> TestTrait for GreeterOutput<A, B>
|
||||
where
|
||||
A: TestTrait<Output = ()>,
|
||||
B: TestTrait<Output = ()>,
|
||||
{
|
||||
type Output = ();
|
||||
}
|
||||
|
||||
enum GreeterOutput<A, B>
|
||||
where
|
||||
A: TestTrait<Output = ()>,
|
||||
B: TestTrait<Output = ()>,
|
||||
{
|
||||
SayHello(A),
|
||||
SayGoodbye(B),
|
||||
}
|
||||
|
||||
trait Greeter {
|
||||
fn test_func(&self, func: &str) -> impl TestTrait<Output = ()> {
|
||||
match func {
|
||||
"SayHello" => GreeterOutput::SayHello(TestA {}),
|
||||
"SayGoodbye" => GreeterOutput::SayGoodbye(TestB {}),
|
||||
_ => GreeterOutput::SayHello(TestA {}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/box-coerce-span-in-default.rs:3:12
|
||||
|
|
||||
LL | #![feature(return_position_impl_trait_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
Loading…
Reference in New Issue
Block a user