Skip to content

Commit 132a288

Browse files
Use alias-eq in structural normalization
1 parent 2a76340 commit 132a288

File tree

7 files changed

+50
-50
lines changed

7 files changed

+50
-50
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1498,7 +1498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14981498
let ty = self.resolve_vars_with_obligations(ty);
14991499

15001500
if self.next_trait_solver()
1501-
&& let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = ty.kind()
1501+
&& let ty::Alias(..) = ty.kind()
15021502
{
15031503
match self
15041504
.at(&self.misc(sp), self.param_env)

compiler/rustc_trait_selection/src/traits/structural_normalize.rs

+31-30
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
33
use rustc_infer::traits::{FulfillmentError, TraitEngine};
44
use rustc_middle::ty::{self, Ty};
55

6-
use crate::traits::{query::evaluate_obligation::InferCtxtExt, NormalizeExt, Obligation};
6+
use crate::traits::{NormalizeExt, Obligation};
77

88
pub trait StructurallyNormalizeExt<'tcx> {
99
fn structurally_normalize(
@@ -16,42 +16,43 @@ pub trait StructurallyNormalizeExt<'tcx> {
1616
impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
1717
fn structurally_normalize(
1818
&self,
19-
mut ty: Ty<'tcx>,
19+
ty: Ty<'tcx>,
2020
fulfill_cx: &mut dyn TraitEngine<'tcx>,
2121
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
2222
assert!(!ty.is_ty_var(), "should have resolved vars before calling");
2323

2424
if self.infcx.next_trait_solver() {
25-
// FIXME(-Znext-solver): correctly handle
26-
// overflow here.
27-
for _ in 0..256 {
28-
let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, alias) = *ty.kind() else {
29-
break;
30-
};
31-
32-
let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
33-
kind: TypeVariableOriginKind::NormalizeProjectionType,
34-
span: self.cause.span,
35-
});
36-
let obligation = Obligation::new(
37-
self.infcx.tcx,
38-
self.cause.clone(),
39-
self.param_env,
40-
ty::NormalizesTo { alias, term: new_infer_ty.into() },
41-
);
42-
if self.infcx.predicate_may_hold(&obligation) {
43-
fulfill_cx.register_predicate_obligation(self.infcx, obligation);
44-
let errors = fulfill_cx.select_where_possible(self.infcx);
45-
if !errors.is_empty() {
46-
return Err(errors);
47-
}
48-
ty = self.infcx.resolve_vars_if_possible(new_infer_ty);
49-
} else {
50-
break;
51-
}
25+
// FIXME(-Znext-solver): Should we resolve opaques here?
26+
let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = *ty.kind() else {
27+
return Ok(ty);
28+
};
29+
30+
let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
31+
kind: TypeVariableOriginKind::NormalizeProjectionType,
32+
span: self.cause.span,
33+
});
34+
35+
// We simply emit an `alias-eq` goal here, since that will take care of
36+
// normalizing the LHS of the projection until it is a rigid projection
37+
// (or a not-yet-defined opaque in scope).
38+
let obligation = Obligation::new(
39+
self.infcx.tcx,
40+
self.cause.clone(),
41+
self.param_env,
42+
ty::PredicateKind::AliasRelate(
43+
ty.into(),
44+
new_infer_ty.into(),
45+
ty::AliasRelationDirection::Equate,
46+
),
47+
);
48+
49+
fulfill_cx.register_predicate_obligation(self.infcx, obligation);
50+
let errors = fulfill_cx.select_where_possible(self.infcx);
51+
if !errors.is_empty() {
52+
return Err(errors);
5253
}
5354

54-
Ok(ty)
55+
Ok(self.infcx.resolve_vars_if_possible(new_infer_ty))
5556
} else {
5657
Ok(self.normalize(ty).into_value_registering_obligations(self.infcx, fulfill_cx))
5758
}

tests/ui/traits/next-solver/alias-bound-unsound.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn main() {
2323
let x = String::from("hello, world");
2424
drop(<() as Foo>::copy_me(&x));
2525
//~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized`
26-
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
26+
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
2727
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
2828
//~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
2929
//~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`

tests/ui/traits/next-solver/alias-bound-unsound.stderr

+1-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ LL | drop(<() as Foo>::copy_me(&x));
1919
|
2020
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
2121

22-
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
22+
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
2323
--> $DIR/alias-bound-unsound.rs:24:10
2424
|
2525
LL | drop(<() as Foo>::copy_me(&x));
@@ -59,7 +59,6 @@ LL | drop(<() as Foo>::copy_me(&x));
5959
| ^^^^^^^^^^^^^^^^^^^^^^^^
6060
|
6161
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
62-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
6362

6463
error: aborting due to 7 previous errors
6564

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// compile-flags: -Znext-solver
2+
// check-pass
3+
4+
trait Trait {
5+
type Assoc;
6+
}
7+
8+
fn call<T: Trait>(_: <T as Trait>::Assoc, _: T) {}
9+
10+
fn foo<T: Trait>(rigid: <T as Trait>::Assoc, t: T) {
11+
// Check that we can coerce `<?0 as Trait>::Assoc` to `<T as Trait>::Assoc`.
12+
call::<_ /* ?0 */>(rigid, t);
13+
}
14+
15+
fn main() {}

tests/ui/traits/next-solver/object-unsafety.rs

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ pub fn copy_any<T>(t: &T) -> T {
1313
//~^ ERROR the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
1414
//~| ERROR the trait bound `dyn Setup<From = T>: Setup` is not satisfied
1515
//~| ERROR mismatched types
16-
//~| ERROR mismatched types
1716
//~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
1817
//~| ERROR the size for values of type `<dyn Setup<From = T> as Setup>::From` cannot be known at compilation time
1918

tests/ui/traits/next-solver/object-unsafety.stderr

+1-15
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,6 @@ note: function defined here
3636
LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
3737
| ^^^^ --------------
3838

39-
error[E0308]: mismatched types
40-
--> $DIR/object-unsafety.rs:12:5
41-
|
42-
LL | pub fn copy_any<T>(t: &T) -> T {
43-
| - - expected `T` because of return type
44-
| |
45-
| expected this type parameter
46-
LL | copy::<dyn Setup<From=T>>(t)
47-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
48-
|
49-
= note: expected type parameter `T`
50-
found associated type `<dyn Setup<From = T> as Setup>::From`
51-
= note: you might be missing a type parameter or trait bound
52-
5339
error: the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
5440
--> $DIR/object-unsafety.rs:12:5
5541
|
@@ -72,7 +58,7 @@ help: consider further restricting the associated type
7258
LL | pub fn copy_any<T>(t: &T) -> T where <dyn Setup<From = T> as Setup>::From: Sized {
7359
| +++++++++++++++++++++++++++++++++++++++++++++++++
7460

75-
error: aborting due to 6 previous errors
61+
error: aborting due to 5 previous errors
7662

7763
Some errors have detailed explanations: E0277, E0308.
7864
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)