Skip to content

Commit fd2038d

Browse files
Make sure the alias is actually rigid
1 parent 50b8029 commit fd2038d

20 files changed

+530
-112
lines changed

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

+51-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::solve::assembly::{self, Candidate};
1515
use crate::solve::inspect::ProbeKind;
1616
use crate::solve::{
1717
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
18-
NoSolution, QueryResult,
18+
NoSolution, QueryResult, Reveal,
1919
};
2020

2121
impl<D, I> EvalCtxt<'_, D>
@@ -39,11 +39,58 @@ where
3939
Err(NoSolution) => {
4040
let Goal { param_env, predicate: NormalizesTo { alias, term } } = goal;
4141
self.relate_rigid_alias_non_alias(param_env, alias, ty::Invariant, term)?;
42+
self.add_rigid_constraints(param_env, alias)?;
4243
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
4344
}
4445
}
4546
}
4647

48+
/// Register any obligations that are used to validate that an alias should be
49+
/// treated as rigid.
50+
///
51+
/// An alias may be considered rigid if it fails normalization, but we also don't
52+
/// want to consider aliases that are not well-formed to be rigid simply because
53+
/// they fail normalization.
54+
///
55+
/// For example, some `<T as Trait>::Assoc` where `T: Trait` does not hold, or an
56+
/// opaque type whose hidden type doesn't actually satisfy the opaque item bounds.
57+
fn add_rigid_constraints(
58+
&mut self,
59+
param_env: I::ParamEnv,
60+
rigid_alias: ty::AliasTerm<I>,
61+
) -> Result<(), NoSolution> {
62+
match rigid_alias.kind(self.cx()) {
63+
// Projections are rigid only if their trait ref holds.
64+
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
65+
let trait_ref = rigid_alias.trait_ref(self.cx());
66+
self.add_goal(GoalSource::Misc, Goal::new(self.cx(), param_env, trait_ref));
67+
Ok(())
68+
}
69+
ty::AliasTermKind::OpaqueTy => {
70+
match param_env.reveal() {
71+
// In user-facing mode, paques are only rigid if we may not define it.
72+
Reveal::UserFacing => {
73+
if rigid_alias
74+
.def_id
75+
.as_local()
76+
.is_some_and(|def_id| self.can_define_opaque_ty(def_id))
77+
{
78+
Err(NoSolution)
79+
} else {
80+
Ok(())
81+
}
82+
}
83+
// Opaques are never rigid in reveal-all mode.
84+
Reveal::All => Err(NoSolution),
85+
}
86+
}
87+
// FIXME(generic_const_exprs): we would need to support generic consts here
88+
ty::AliasTermKind::UnevaluatedConst => Err(NoSolution),
89+
// Inherent and weak types are never rigid. This type must not be well-formed.
90+
ty::AliasTermKind::WeakTy | ty::AliasTermKind::InherentTy => Err(NoSolution),
91+
}
92+
}
93+
4794
/// Normalize the given alias by at least one step. If the alias is rigid, this
4895
/// returns `NoSolution`.
4996
#[instrument(level = "trace", skip(self), ret)]
@@ -124,6 +171,7 @@ where
124171
ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term);
125172

126173
// Add GAT where clauses from the trait's definition
174+
// FIXME: We don't need these, since these are the type's own WF obligations.
127175
ecx.add_goals(
128176
GoalSource::Misc,
129177
cx.own_predicates_of(goal.predicate.def_id())
@@ -179,7 +227,8 @@ where
179227
.map(|pred| goal.with(cx, pred));
180228
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
181229

182-
// Add GAT where clauses from the trait's definition
230+
// Add GAT where clauses from the trait's definition.
231+
// FIXME: We don't need these, since these are the type's own WF obligations.
183232
ecx.add_goals(
184233
GoalSource::Misc,
185234
cx.own_predicates_of(goal.predicate.def_id())

tests/ui/associated-types/defaults-unsound-62211-1.next.stderr

+17-4
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,29 @@ help: consider further restricting `Self`
3131
LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
3232
| +++++++++++++++++++++++++
3333

34-
error[E0277]: the trait bound `Self: Deref` is not satisfied
34+
error[E0271]: type mismatch resolving `<Self as Deref>::Target normalizes-to <Self as Deref>::Target`
3535
--> $DIR/defaults-unsound-62211-1.rs:24:96
3636
|
3737
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
38-
| ^^^^ the trait `Deref` is not implemented for `Self`
38+
| ^^^^ types differ
3939
|
4040
note: required by a bound in `UncheckedCopy::Output`
4141
--> $DIR/defaults-unsound-62211-1.rs:24:31
4242
|
4343
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
4444
| ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
45+
46+
error[E0277]: the trait bound `Self: Deref` is not satisfied
47+
--> $DIR/defaults-unsound-62211-1.rs:24:96
48+
|
49+
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
50+
| ^^^^ the trait `Deref` is not implemented for `Self`
51+
|
52+
note: required by a bound in `UncheckedCopy::Output`
53+
--> $DIR/defaults-unsound-62211-1.rs:24:25
54+
|
55+
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
56+
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
4557
help: consider further restricting `Self`
4658
|
4759
LL | trait UncheckedCopy: Sized + Deref {
@@ -63,6 +75,7 @@ help: consider further restricting `Self`
6375
LL | trait UncheckedCopy: Sized + Copy {
6476
| ++++++
6577

66-
error: aborting due to 4 previous errors
78+
error: aborting due to 5 previous errors
6779

68-
For more information about this error, try `rustc --explain E0277`.
80+
Some errors have detailed explanations: E0271, E0277.
81+
For more information about an error, try `rustc --explain E0271`.

tests/ui/associated-types/defaults-unsound-62211-2.next.stderr

+17-4
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,29 @@ help: consider further restricting `Self`
3131
LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
3232
| +++++++++++++++++++++++++
3333

34-
error[E0277]: the trait bound `Self: Deref` is not satisfied
34+
error[E0271]: type mismatch resolving `<Self as Deref>::Target normalizes-to <Self as Deref>::Target`
3535
--> $DIR/defaults-unsound-62211-2.rs:24:96
3636
|
3737
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
38-
| ^^^^ the trait `Deref` is not implemented for `Self`
38+
| ^^^^ types differ
3939
|
4040
note: required by a bound in `UncheckedCopy::Output`
4141
--> $DIR/defaults-unsound-62211-2.rs:24:31
4242
|
4343
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
4444
| ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
45+
46+
error[E0277]: the trait bound `Self: Deref` is not satisfied
47+
--> $DIR/defaults-unsound-62211-2.rs:24:96
48+
|
49+
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
50+
| ^^^^ the trait `Deref` is not implemented for `Self`
51+
|
52+
note: required by a bound in `UncheckedCopy::Output`
53+
--> $DIR/defaults-unsound-62211-2.rs:24:25
54+
|
55+
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
56+
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
4557
help: consider further restricting `Self`
4658
|
4759
LL | trait UncheckedCopy: Sized + Deref {
@@ -63,6 +75,7 @@ help: consider further restricting `Self`
6375
LL | trait UncheckedCopy: Sized + Copy {
6476
| ++++++
6577

66-
error: aborting due to 4 previous errors
78+
error: aborting due to 5 previous errors
6779

68-
For more information about this error, try `rustc --explain E0277`.
80+
Some errors have detailed explanations: E0271, E0277.
81+
For more information about an error, try `rustc --explain E0271`.
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
error[E0271]: type mismatch resolving `<<T as SubEncoder>::ActualSize as Add>::Output normalizes-to <<T as SubEncoder>::ActualSize as Add>::Output`
2+
--> $DIR/issue-54108.rs:23:17
3+
|
4+
LL | type Size = <Self as SubEncoder>::ActualSize;
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
6+
|
7+
note: required by a bound in `Encoder::Size`
8+
--> $DIR/issue-54108.rs:8:20
9+
|
10+
LL | type Size: Add<Output = Self::Size>;
11+
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size`
12+
113
error[E0277]: cannot add `<T as SubEncoder>::ActualSize` to `<T as SubEncoder>::ActualSize`
214
--> $DIR/issue-54108.rs:23:17
315
|
@@ -6,15 +18,16 @@ LL | type Size = <Self as SubEncoder>::ActualSize;
618
|
719
= help: the trait `Add` is not implemented for `<T as SubEncoder>::ActualSize`
820
note: required by a bound in `Encoder::Size`
9-
--> $DIR/issue-54108.rs:8:20
21+
--> $DIR/issue-54108.rs:8:16
1022
|
1123
LL | type Size: Add<Output = Self::Size>;
12-
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size`
24+
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size`
1325
help: consider further restricting the associated type
1426
|
1527
LL | T: SubEncoder, <T as SubEncoder>::ActualSize: Add
1628
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1729

18-
error: aborting due to 1 previous error
30+
error: aborting due to 2 previous errors
1931

20-
For more information about this error, try `rustc --explain E0277`.
32+
Some errors have detailed explanations: E0271, E0277.
33+
For more information about an error, try `rustc --explain E0271`.

tests/ui/for/issue-20605.next.stderr

+2-9
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,6 @@ help: consider mutably borrowing here
1111
LL | for item in &mut *things { *item = 0 }
1212
| ++++
1313

14-
error[E0614]: type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced
15-
--> $DIR/issue-20605.rs:6:27
16-
|
17-
LL | for item in *things { *item = 0 }
18-
| ^^^^^
19-
20-
error: aborting due to 2 previous errors
14+
error: aborting due to 1 previous error
2115

22-
Some errors have detailed explanations: E0277, E0614.
23-
For more information about an error, try `rustc --explain E0277`.
16+
For more information about this error, try `rustc --explain E0277`.

tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr

+10-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ help: consider specifying the generic arguments
1515
LL | cmp_eq::<A, B, O>
1616
| +++++++++++
1717

18-
error: aborting due to 1 previous error
18+
error[E0271]: type mismatch resolving `build_expression<A, B, O>::{opaque#0} normalizes-to _`
19+
--> $DIR/ambig-hr-projection-issue-93340.rs:14:1
20+
|
21+
LL | / fn build_expression<A: Scalar, B: Scalar, O: Scalar>(
22+
LL | | ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O {
23+
| |_________________________________________________^ types differ
24+
25+
error: aborting due to 2 previous errors
1926

20-
For more information about this error, try `rustc --explain E0283`.
27+
Some errors have detailed explanations: E0271, E0283.
28+
For more information about an error, try `rustc --explain E0271`.

tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr

+23-5
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,32 @@ LL | #![feature(lazy_type_alias)]
77
= note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
88
= note: `#[warn(incomplete_features)]` on by default
99

10-
error[E0277]: the size for values of type `A<usize>` cannot be known at compilation time
10+
error[E0271]: type mismatch resolving `A<usize> normalizes-to _`
1111
--> $DIR/alias-bounds-when-not-wf.rs:16:13
1212
|
1313
LL | fn hello(_: W<A<usize>>) {}
14-
| ^^^^^^^^^^^ doesn't have a size known at compile-time
14+
| ^^^^^^^^^^^ types differ
15+
16+
error[E0271]: type mismatch resolving `A<usize> normalizes-to _`
17+
--> $DIR/alias-bounds-when-not-wf.rs:16:10
1518
|
16-
= help: the trait `Sized` is not implemented for `A<usize>`
19+
LL | fn hello(_: W<A<usize>>) {}
20+
| ^ types differ
21+
22+
error[E0271]: type mismatch resolving `A<usize> normalizes-to _`
23+
--> $DIR/alias-bounds-when-not-wf.rs:16:10
24+
|
25+
LL | fn hello(_: W<A<usize>>) {}
26+
| ^ types differ
27+
|
28+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
29+
30+
error[E0271]: type mismatch resolving `A<usize> normalizes-to _`
31+
--> $DIR/alias-bounds-when-not-wf.rs:16:1
32+
|
33+
LL | fn hello(_: W<A<usize>>) {}
34+
| ^^^^^^^^^^^^^^^^^^^^^^^^ types differ
1735

18-
error: aborting due to 1 previous error; 1 warning emitted
36+
error: aborting due to 4 previous errors; 1 warning emitted
1937

20-
For more information about this error, try `rustc --explain E0277`.
38+
For more information about this error, try `rustc --explain E0271`.

tests/ui/impl-trait/method-resolution4.next.stderr

+41-9
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,51 @@ error[E0282]: type annotations needed
44
LL | foo(false).next().unwrap();
55
| ^^^^^^^^^^ cannot infer type
66

7-
error[E0308]: mismatched types
8-
--> $DIR/method-resolution4.rs:16:5
7+
error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _`
8+
--> $DIR/method-resolution4.rs:13:9
9+
|
10+
LL | foo(false).next().unwrap();
11+
| ^^^^^^^^^^ types differ
12+
13+
error[E0277]: the size for values of type `impl Iterator<Item = ()>` cannot be known at compilation time
14+
--> $DIR/method-resolution4.rs:11:20
915
|
1016
LL | fn foo(b: bool) -> impl Iterator<Item = ()> {
11-
| ------------------------ the expected opaque type
12-
...
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
18+
|
19+
= help: the trait `Sized` is not implemented for `impl Iterator<Item = ()>`
20+
= note: the return type of a function must have a statically known size
21+
22+
error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _`
23+
--> $DIR/method-resolution4.rs:16:5
24+
|
1325
LL | std::iter::empty()
1426
| ^^^^^^^^^^^^^^^^^^ types differ
27+
28+
error[E0277]: the size for values of type `impl Iterator<Item = ()>` cannot be known at compilation time
29+
--> $DIR/method-resolution4.rs:13:9
1530
|
16-
= note: expected opaque type `impl Iterator<Item = ()>`
17-
found struct `std::iter::Empty<_>`
31+
LL | foo(false).next().unwrap();
32+
| ^^^^^^^^^^ doesn't have a size known at compile-time
33+
|
34+
= help: the trait `Sized` is not implemented for `impl Iterator<Item = ()>`
35+
= note: the return type of a function must have a statically known size
36+
37+
error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _`
38+
--> $DIR/method-resolution4.rs:13:9
39+
|
40+
LL | foo(false).next().unwrap();
41+
| ^^^^^^^^^^ types differ
42+
|
43+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
44+
45+
error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _`
46+
--> $DIR/method-resolution4.rs:11:1
47+
|
48+
LL | fn foo(b: bool) -> impl Iterator<Item = ()> {
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
1850

19-
error: aborting due to 2 previous errors
51+
error: aborting due to 7 previous errors
2052

21-
Some errors have detailed explanations: E0282, E0308.
22-
For more information about an error, try `rustc --explain E0282`.
53+
Some errors have detailed explanations: E0271, E0277, E0282.
54+
For more information about an error, try `rustc --explain E0271`.

0 commit comments

Comments
 (0)