Skip to content

Commit 65ab663

Browse files
authoredFeb 13, 2024
Rollup merge of #120549 - lcnr:errs-showcase, r=compiler-errors
modify alias-relate to also normalize ambiguous opaques allows a bunch of further cleanups and generally simplifies the type system. To handle rust-lang/trait-system-refactor-initiative#8 we'll have to add a some additional complexity to the `(Alias, Infer)` branches in alias-relate, so removing the opaque type special case here is really valuable. It does worsen `deduce_closure_signature` and friends even more as they now receive an inference variable which is only constrained via an `AliasRelate` goal. These probably have to look into alias relate goals somehow. Leaving that for a future PR as this is something we'll have to tackle regardless. r? `@compiler-errors`
2 parents 5d9c899 + 51a1000 commit 65ab663

23 files changed

+186
-214
lines changed
 

‎compiler/rustc_hir_typeck/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ fn typeck_with_fallback<'tcx>(
304304

305305
let typeck_results = fcx.resolve_type_vars_in_body(body);
306306

307+
// We clone the defined opaque types during writeback in the new solver
308+
// because we have to use them during normalization.
309+
let _ = fcx.infcx.take_opaque_types();
310+
307311
// Consistency check our TypeckResults instance can hold all ItemLocalIds
308312
// it will need to hold.
309313
assert_eq!(typeck_results.hir_owner, id.owner);

‎compiler/rustc_hir_typeck/src/writeback.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,15 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
562562

563563
#[instrument(skip(self), level = "debug")]
564564
fn visit_opaque_types(&mut self) {
565-
let opaque_types = self.fcx.infcx.take_opaque_types();
565+
// We clone the opaques instead of stealing them here as they are still used for
566+
// normalization in the next generation trait solver.
567+
//
568+
// FIXME(-Znext-solver): Opaque types defined after this would simply get dropped
569+
// at the end of typeck. While this seems unlikely to happen in practice this
570+
// should still get fixed. Either by preventing writeback from defining new opaque
571+
// types or by using this function at the end of writeback and running it as a
572+
// fixpoint.
573+
let opaque_types = self.fcx.infcx.clone_opaque_types();
566574
for (opaque_type_key, decl) in opaque_types {
567575
let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span);
568576
let opaque_type_key = self.resolve(opaque_type_key, &decl.hidden_type.span);

‎compiler/rustc_infer/src/infer/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,12 @@ impl<'tcx> InferCtxt<'tcx> {
13251325
std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
13261326
}
13271327

1328+
#[instrument(level = "debug", skip(self), ret)]
1329+
pub fn clone_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
1330+
debug_assert_ne!(self.defining_use_anchor, DefiningAnchor::Error);
1331+
self.inner.borrow().opaque_type_storage.opaque_types.clone()
1332+
}
1333+
13281334
pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
13291335
self.resolve_vars_if_possible(t).to_string()
13301336
}

‎compiler/rustc_trait_selection/src/solve/alias_relate.rs

Lines changed: 40 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,27 @@
33
//! of our more general approach to "lazy normalization".
44
//!
55
//! This is done by first normalizing both sides of the goal, ending up in
6-
//! either a concrete type, rigid projection, opaque, or an infer variable.
6+
//! either a concrete type, rigid alias, or an infer variable.
77
//! These are related further according to the rules below:
88
//!
9-
//! (1.) If we end up with a rigid projection and a rigid projection, then we
10-
//! relate those projections structurally.
9+
//! (1.) If we end up with two rigid aliases, then we relate them structurally.
1110
//!
12-
//! (2.) If we end up with a rigid projection and an alias, then the opaque will
13-
//! have its hidden type defined to be that rigid projection.
14-
//!
15-
//! (3.) If we end up with an opaque and an opaque, then we assemble two
16-
//! candidates, one defining the LHS to be the hidden type of the RHS, and vice
17-
//! versa.
18-
//!
19-
//! (4.) If we end up with an infer var and an opaque or rigid projection, then
11+
//! (2.) If we end up with an infer var and a rigid alias, then
2012
//! we assign the alias to the infer var.
2113
//!
22-
//! (5.) If we end up with an opaque and a rigid (non-projection) type, then we
23-
//! define the hidden type of the opaque to be the rigid type.
24-
//!
25-
//! (6.) Otherwise, if we end with two rigid (non-projection) or infer types,
14+
//! (3.) Otherwise, if we end with two rigid (non-projection) or infer types,
2615
//! relate them structurally.
16+
//!
17+
//! Subtle: when relating an opaque to another type, we emit a
18+
//! `NormalizesTo(opaque, ?fresh_var)` goal when trying to normalize the opaque.
19+
//! This nested goal starts out as ambiguous and does not actually define the opaque.
20+
//! However, if `?fresh_var` ends up geteting equated to another type, we retry the
21+
//! `NormalizesTo` goal, at which point the opaque is actually defined.
2722
2823
use super::{EvalCtxt, GoalSource};
29-
use rustc_infer::infer::DefineOpaqueTypes;
3024
use rustc_infer::traits::query::NoSolution;
3125
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
32-
use rustc_middle::ty;
26+
use rustc_middle::ty::{self, Ty};
3327

3428
impl<'tcx> EvalCtxt<'_, 'tcx> {
3529
#[instrument(level = "debug", skip(self), ret)]
@@ -59,37 +53,32 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
5953
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
6054
}
6155

62-
(Some(alias), None) => {
56+
(Some(_), None) => {
6357
if rhs.is_infer() {
6458
self.relate(param_env, lhs, variance, rhs)?;
6559
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
66-
} else if alias.is_opaque(tcx) {
67-
// FIXME: This doesn't account for variance.
68-
self.define_opaque(param_env, alias, rhs)
6960
} else {
7061
Err(NoSolution)
7162
}
7263
}
73-
(None, Some(alias)) => {
64+
(None, Some(_)) => {
7465
if lhs.is_infer() {
7566
self.relate(param_env, lhs, variance, rhs)?;
7667
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
77-
} else if alias.is_opaque(tcx) {
78-
// FIXME: This doesn't account for variance.
79-
self.define_opaque(param_env, alias, lhs)
8068
} else {
8169
Err(NoSolution)
8270
}
8371
}
8472

8573
(Some(alias_lhs), Some(alias_rhs)) => {
86-
self.relate_rigid_alias_or_opaque(param_env, alias_lhs, variance, alias_rhs)
74+
self.relate(param_env, alias_lhs, variance, alias_rhs)?;
75+
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
8776
}
8877
}
8978
}
9079

9180
// FIXME: This needs a name that reflects that it's okay to bottom-out with an inference var.
92-
/// Normalize the `term` to equate it later. This does not define opaque types.
81+
/// Normalize the `term` to equate it later.
9382
#[instrument(level = "debug", skip(self, param_env), ret)]
9483
fn try_normalize_term(
9584
&mut self,
@@ -98,10 +87,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
9887
) -> Result<Option<ty::Term<'tcx>>, NoSolution> {
9988
match term.unpack() {
10089
ty::TermKind::Ty(ty) => {
101-
// We do no define opaque types here but instead do so in `relate_rigid_alias_or_opaque`.
102-
Ok(self
103-
.try_normalize_ty_recur(param_env, DefineOpaqueTypes::No, 0, ty)
104-
.map(Into::into))
90+
Ok(self.try_normalize_ty_recur(param_env, 0, ty).map(Into::into))
10591
}
10692
ty::TermKind::Const(_) => {
10793
if let Some(alias) = term.to_alias_ty(self.tcx()) {
@@ -119,51 +105,34 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
119105
}
120106
}
121107

122-
fn define_opaque(
108+
fn try_normalize_ty_recur(
123109
&mut self,
124110
param_env: ty::ParamEnv<'tcx>,
125-
opaque: ty::AliasTy<'tcx>,
126-
term: ty::Term<'tcx>,
127-
) -> QueryResult<'tcx> {
128-
self.add_goal(
129-
GoalSource::Misc,
130-
Goal::new(self.tcx(), param_env, ty::NormalizesTo { alias: opaque, term }),
131-
);
132-
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
133-
}
134-
135-
fn relate_rigid_alias_or_opaque(
136-
&mut self,
137-
param_env: ty::ParamEnv<'tcx>,
138-
lhs: ty::AliasTy<'tcx>,
139-
variance: ty::Variance,
140-
rhs: ty::AliasTy<'tcx>,
141-
) -> QueryResult<'tcx> {
142-
let tcx = self.tcx();
143-
let mut candidates = vec![];
144-
if lhs.is_opaque(tcx) {
145-
candidates.extend(
146-
self.probe_misc_candidate("define-lhs-opaque")
147-
.enter(|ecx| ecx.define_opaque(param_env, lhs, rhs.to_ty(tcx).into())),
148-
);
111+
depth: usize,
112+
ty: Ty<'tcx>,
113+
) -> Option<Ty<'tcx>> {
114+
if !self.tcx().recursion_limit().value_within_limit(depth) {
115+
return None;
149116
}
150117

151-
if rhs.is_opaque(tcx) {
152-
candidates.extend(
153-
self.probe_misc_candidate("define-rhs-opaque")
154-
.enter(|ecx| ecx.define_opaque(param_env, rhs, lhs.to_ty(tcx).into())),
155-
);
156-
}
157-
158-
candidates.extend(self.probe_misc_candidate("args-relate").enter(|ecx| {
159-
ecx.relate(param_env, lhs, variance, rhs)?;
160-
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
161-
}));
118+
let ty::Alias(_, alias) = *ty.kind() else {
119+
return Some(ty);
120+
};
162121

163-
if let Some(result) = self.try_merge_responses(&candidates) {
164-
Ok(result)
165-
} else {
166-
self.flounder(&candidates)
122+
match self.commit_if_ok(|this| {
123+
let normalized_ty = this.next_ty_infer();
124+
let normalizes_to_goal = Goal::new(
125+
this.tcx(),
126+
param_env,
127+
ty::NormalizesTo { alias, term: normalized_ty.into() },
128+
);
129+
this.add_goal(GoalSource::Misc, normalizes_to_goal);
130+
this.try_evaluate_added_goals()?;
131+
let ty = this.resolve_vars_if_possible(normalized_ty);
132+
Ok(this.try_normalize_ty_recur(param_env, depth + 1, ty))
133+
}) {
134+
Ok(ty) => ty,
135+
Err(NoSolution) => Some(ty),
167136
}
168137
}
169138
}

‎compiler/rustc_trait_selection/src/solve/assembly/mod.rs

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -276,11 +276,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
276276
&mut self,
277277
goal: Goal<'tcx, G>,
278278
) -> Vec<Candidate<'tcx>> {
279-
let Some(normalized_self_ty) =
280-
self.try_normalize_ty(goal.param_env, goal.predicate.self_ty())
279+
let Ok(normalized_self_ty) =
280+
self.structurally_normalize_ty(goal.param_env, goal.predicate.self_ty())
281281
else {
282-
debug!("overflow while evaluating self type");
283-
return self.forced_ambiguity(MaybeCause::Overflow);
282+
return vec![];
284283
};
285284

286285
if normalized_self_ty.is_ty_var() {
@@ -635,19 +634,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
635634
return;
636635
}
637636

638-
match self.try_normalize_ty(goal.param_env, alias_ty.self_ty()) {
639-
// Recurse on the self type of the projection.
640-
Some(next_self_ty) => {
641-
self.assemble_alias_bound_candidates_recur(next_self_ty, goal, candidates);
642-
}
643-
// Bail if we overflow when normalizing, adding an ambiguous candidate.
644-
None => {
645-
if let Ok(result) =
646-
self.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW)
647-
{
648-
candidates.push(Candidate { source: CandidateSource::AliasBound, result });
649-
}
637+
// Recurse on the self type of the projection.
638+
match self.structurally_normalize_ty(goal.param_env, alias_ty.self_ty()) {
639+
Ok(next_self_ty) => {
640+
self.assemble_alias_bound_candidates_recur(next_self_ty, goal, candidates)
650641
}
642+
Err(NoSolution) => {}
651643
}
652644
}
653645

@@ -857,19 +849,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
857849
let tcx = self.tcx();
858850
let result = self.probe_misc_candidate("coherence unknowable").enter(|ecx| {
859851
let trait_ref = goal.predicate.trait_ref(tcx);
860-
#[derive(Debug)]
861-
struct Overflow;
862-
let lazily_normalize_ty = |ty| match ecx.try_normalize_ty(goal.param_env, ty) {
863-
Some(ty) => Ok(ty),
864-
None => Err(Overflow),
865-
};
852+
let lazily_normalize_ty = |ty| ecx.structurally_normalize_ty(goal.param_env, ty);
866853

867-
match coherence::trait_ref_is_knowable(tcx, trait_ref, lazily_normalize_ty) {
868-
Err(Overflow) => {
869-
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW)
870-
}
871-
Ok(Ok(())) => Err(NoSolution),
872-
Ok(Err(_)) => {
854+
match coherence::trait_ref_is_knowable(tcx, trait_ref, lazily_normalize_ty)? {
855+
Ok(()) => Err(NoSolution),
856+
Err(_) => {
873857
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
874858
}
875859
}

‎compiler/rustc_trait_selection/src/solve/mod.rs

Lines changed: 19 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@
1515
//! about it on zulip.
1616
use rustc_hir::def_id::DefId;
1717
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
18-
use rustc_infer::infer::DefineOpaqueTypes;
1918
use rustc_infer::traits::query::NoSolution;
2019
use rustc_middle::infer::canonical::CanonicalVarInfos;
2120
use rustc_middle::traits::solve::{
2221
CanonicalResponse, Certainty, ExternalConstraintsData, Goal, GoalSource, IsNormalizesToHack,
2322
QueryResult, Response,
2423
};
25-
use rustc_middle::traits::Reveal;
26-
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, UniverseIndex};
24+
use rustc_middle::ty::{self, AliasRelationDirection, Ty, TyCtxt, UniverseIndex};
2725
use rustc_middle::ty::{
2826
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate,
2927
};
@@ -267,71 +265,32 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
267265
Ok(self.make_ambiguous_response_no_constraints(maybe_cause))
268266
}
269267

270-
/// Normalize a type when it is structually matched on.
268+
/// Normalize a type for when it is structurally matched on.
271269
///
272-
/// In nearly all cases this function must be used before matching on a type.
270+
/// This function is necessary in nearly all cases before matching on a type.
273271
/// Not doing so is likely to be incomplete and therefore unsound during
274272
/// coherence.
275-
#[instrument(level = "debug", skip(self), ret)]
276-
fn try_normalize_ty(
277-
&mut self,
278-
param_env: ty::ParamEnv<'tcx>,
279-
ty: Ty<'tcx>,
280-
) -> Option<Ty<'tcx>> {
281-
self.try_normalize_ty_recur(param_env, DefineOpaqueTypes::Yes, 0, ty)
282-
}
283-
284-
fn try_normalize_ty_recur(
273+
fn structurally_normalize_ty(
285274
&mut self,
286275
param_env: ty::ParamEnv<'tcx>,
287-
define_opaque_types: DefineOpaqueTypes,
288-
depth: usize,
289276
ty: Ty<'tcx>,
290-
) -> Option<Ty<'tcx>> {
291-
if !self.tcx().recursion_limit().value_within_limit(depth) {
292-
return None;
293-
}
294-
295-
let ty::Alias(kind, alias) = *ty.kind() else {
296-
return Some(ty);
297-
};
298-
299-
// We do no always define opaque types eagerly to allow non-defining uses
300-
// in the defining scope. However, if we can unify this opaque to an existing
301-
// opaque, then we should attempt to eagerly reveal the opaque, and we fall
302-
// through.
303-
if let DefineOpaqueTypes::No = define_opaque_types
304-
&& let Reveal::UserFacing = param_env.reveal()
305-
&& let ty::Opaque = kind
306-
&& let Some(def_id) = alias.def_id.as_local()
307-
&& self.can_define_opaque_ty(def_id)
308-
{
309-
if self
310-
.unify_existing_opaque_tys(
311-
param_env,
312-
OpaqueTypeKey { def_id, args: alias.args },
313-
self.next_ty_infer(),
314-
)
315-
.is_empty()
316-
{
317-
return Some(ty);
318-
}
319-
}
320-
321-
match self.commit_if_ok(|this| {
322-
let normalized_ty = this.next_ty_infer();
323-
let normalizes_to_goal = Goal::new(
324-
this.tcx(),
277+
) -> Result<Ty<'tcx>, NoSolution> {
278+
if let ty::Alias(..) = ty.kind() {
279+
let normalized_ty = self.next_ty_infer();
280+
let alias_relate_goal = Goal::new(
281+
self.tcx(),
325282
param_env,
326-
ty::NormalizesTo { alias, term: normalized_ty.into() },
283+
ty::PredicateKind::AliasRelate(
284+
ty.into(),
285+
normalized_ty.into(),
286+
AliasRelationDirection::Equate,
287+
),
327288
);
328-
this.add_goal(GoalSource::Misc, normalizes_to_goal);
329-
this.try_evaluate_added_goals()?;
330-
let ty = this.resolve_vars_if_possible(normalized_ty);
331-
Ok(this.try_normalize_ty_recur(param_env, define_opaque_types, depth + 1, ty))
332-
}) {
333-
Ok(ty) => ty,
334-
Err(NoSolution) => Some(ty),
289+
self.add_goal(GoalSource::Misc, alias_relate_goal);
290+
self.try_evaluate_added_goals()?;
291+
Ok(self.resolve_vars_if_possible(normalized_ty))
292+
} else {
293+
Ok(ty)
335294
}
336295
}
337296
}

‎compiler/rustc_trait_selection/src/solve/normalizes_to/opaques.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
5858
}
5959
}
6060

61-
let expected = match self.try_normalize_ty(goal.param_env, expected) {
62-
Some(ty) => {
63-
if ty.is_ty_var() {
64-
return self.evaluate_added_goals_and_make_canonical_response(
65-
Certainty::AMBIGUOUS,
66-
);
67-
} else {
68-
ty
69-
}
70-
}
71-
None => {
72-
return self
73-
.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW);
74-
}
75-
};
61+
let expected = self.structurally_normalize_ty(goal.param_env, expected)?;
62+
if expected.is_ty_var() {
63+
return self
64+
.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
65+
}
7666

7767
// Otherwise, define a new opaque type
7868
self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?;

‎compiler/rustc_trait_selection/src/solve/trait_goals.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -584,11 +584,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
584584
let a_ty = goal.predicate.self_ty();
585585
// We need to normalize the b_ty since it's matched structurally
586586
// in the other functions below.
587-
let b_ty = match ecx
588-
.try_normalize_ty(goal.param_env, goal.predicate.trait_ref.args.type_at(1))
589-
{
590-
Some(b_ty) => b_ty,
591-
None => return vec![misc_candidate(ecx, Certainty::OVERFLOW)],
587+
let Ok(b_ty) = ecx.structurally_normalize_ty(
588+
goal.param_env,
589+
goal.predicate.trait_ref.args.type_at(1),
590+
) else {
591+
return vec![];
592592
};
593593

594594
let goal = goal.with(ecx.tcx(), (a_ty, b_ty));
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/recursive-coroutine-boxed.rs:10:23
3+
|
4+
LL | let mut gen = Box::pin(foo());
5+
| ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Box`
6+
...
7+
LL | let mut r = gen.as_mut().resume(());
8+
| ------ type must be known at this point
9+
|
10+
help: consider specifying the generic argument
11+
|
12+
LL | let mut gen = Box::<T>::pin(foo());
13+
| +++++
14+
15+
error[E0282]: type annotations needed
16+
--> $DIR/recursive-coroutine-boxed.rs:10:32
17+
|
18+
LL | let mut gen = Box::pin(foo());
19+
| ^^^^^ cannot infer type for opaque type `impl Coroutine<Yield = (), Return = ()>`
20+
21+
error: aborting due to 2 previous errors
22+
23+
For more information about this error, try `rustc --explain E0282`.

‎tests/ui/impl-trait/recursive-coroutine-boxed.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// check-pass
21
// revisions: current next
2+
//[current] check-pass
33
//[next] compile-flags: -Znext-solver
44
#![feature(coroutines, coroutine_trait)]
55

@@ -8,6 +8,8 @@ use std::ops::{Coroutine, CoroutineState};
88
fn foo() -> impl Coroutine<Yield = (), Return = ()> {
99
|| {
1010
let mut gen = Box::pin(foo());
11+
//[next]~^ ERROR type annotations needed
12+
//[next]~| ERROR type annotations needed
1113
let mut r = gen.as_mut().resume(());
1214
while let CoroutineState::Yielded(v) = r {
1315
yield v;

‎tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0284]: type annotations needed: cannot satisfy `A <: B`
1+
error[E0284]: type annotations needed: cannot satisfy `A == B`
22
--> $DIR/two_tait_defining_each_other2.rs:11:5
33
|
44
LL | x // B's hidden type is A (opaquely)
5-
| ^ cannot satisfy `A <: B`
5+
| ^ cannot satisfy `A == B`
66

77
error: aborting due to 1 previous error
88

‎tests/ui/impl-trait/two_tait_defining_each_other2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ trait Foo {}
1010
fn muh(x: A) -> B {
1111
x // B's hidden type is A (opaquely)
1212
//[current]~^ ERROR opaque type's hidden type cannot be another opaque type
13-
//[next]~^^ ERROR type annotations needed: cannot satisfy `A <: B`
13+
//[next]~^^ ERROR type annotations needed: cannot satisfy `A == B`
1414
}
1515

1616
struct Bar;

‎tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// compile-flags: -Znext-solver
2-
// check-pass
3-
2+
// FIXME(-Znext-solver): This test is currently broken because the `deduce_closure_signature`
3+
// is unable to look at nested obligations.
44
trait Foo {
55
fn test() -> impl Fn(u32) -> u32 {
66
|x| x.count_ones()
7+
//~^ ERROR type annotations needed
78
}
89
}
910

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/deduce-closure-signature-after-normalization.rs:6:10
3+
|
4+
LL | |x| x.count_ones()
5+
| ^ - type must be known at this point
6+
|
7+
help: consider giving this closure parameter an explicit type
8+
|
9+
LL | |x: /* Type */| x.count_ones()
10+
| ++++++++++++
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0282`.
Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
1-
error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
1+
error[E0284]: type annotations needed: cannot satisfy `Foo == _`
22
--> $DIR/dont-type_of-tait-in-defining-scope.rs:15:18
33
|
44
LL | needs_send::<Foo>();
5-
| ^^^
6-
|
7-
= note: cannot satisfy `Foo: Send`
8-
note: required by a bound in `needs_send`
9-
--> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
10-
|
11-
LL | fn needs_send<T: Send>() {}
12-
| ^^^^ required by this bound in `needs_send`
5+
| ^^^ cannot satisfy `Foo == _`
136

147
error: aborting due to 1 previous error
158

16-
For more information about this error, try `rustc --explain E0283`.
9+
For more information about this error, try `rustc --explain E0284`.
Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
1-
error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
1+
error[E0284]: type annotations needed: cannot satisfy `Foo == _`
22
--> $DIR/dont-type_of-tait-in-defining-scope.rs:15:18
33
|
44
LL | needs_send::<Foo>();
5-
| ^^^
6-
|
7-
= note: cannot satisfy `Foo: Send`
8-
note: required by a bound in `needs_send`
9-
--> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
10-
|
11-
LL | fn needs_send<T: Send>() {}
12-
| ^^^^ required by this bound in `needs_send`
5+
| ^^^ cannot satisfy `Foo == _`
136

147
error: aborting due to 1 previous error
158

16-
For more information about this error, try `rustc --explain E0283`.
9+
For more information about this error, try `rustc --explain E0284`.

‎tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn needs_send<T: Send>() {}
1313

1414
fn test(_: Foo) {
1515
needs_send::<Foo>();
16-
//~^ ERROR type annotations needed: cannot satisfy `Foo: Send`
16+
//~^ ERROR type annotations needed: cannot satisfy `Foo == _`
1717
}
1818

1919
fn defines(_: Foo) {

‎tests/ui/type-alias-impl-trait/self-referential-2.stderr renamed to ‎tests/ui/type-alias-impl-trait/self-referential-2.current.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: can't compare `i32` with `Foo`
2-
--> $DIR/self-referential-2.rs:6:13
2+
--> $DIR/self-referential-2.rs:9:13
33
|
44
LL | fn bar() -> Bar {
55
| ^^^ no implementation for `i32 == Foo`
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
// revisions: current next
2+
//[next] compile-flags: -Znext-solver
3+
//[next] check-pass
14
#![feature(type_alias_impl_trait)]
25

36
type Foo = impl std::fmt::Debug;
47
type Bar = impl PartialEq<Foo>;
58

69
fn bar() -> Bar {
7-
42_i32 //~^ ERROR can't compare `i32` with `Foo`
10+
42_i32 //[current]~^ ERROR can't compare `i32` with `Foo`
811
}
912

1013
fn main() {}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0284]: type annotations needed: cannot satisfy `Foo == _`
2+
--> $DIR/type-alias-impl-trait-tuple.rs:21:24
3+
|
4+
LL | Blah { my_foo: make_foo(), my_u8: 12 }
5+
| ^^^^^^^^^^ cannot satisfy `Foo == _`
6+
7+
error[E0284]: type annotations needed: cannot satisfy `Foo == _`
8+
--> $DIR/type-alias-impl-trait-tuple.rs:25:10
9+
|
10+
LL | (self.my_foo, self.my_u8, make_foo())
11+
| ^^^^^^^^^^^ cannot satisfy `Foo == _`
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0284`.

‎tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// check-pass
1+
// revisions: current next
2+
//[next] compile-flags: -Znext-solver
3+
//[current] check-pass
24

35
#![feature(type_alias_impl_trait)]
46
#![allow(dead_code)]
@@ -17,9 +19,11 @@ struct Blah {
1719
impl Blah {
1820
fn new() -> Blah {
1921
Blah { my_foo: make_foo(), my_u8: 12 }
22+
//[next]~^ ERROR type annotations needed: cannot satisfy `Foo == _`
2023
}
2124
fn into_inner(self) -> (Foo, u8, Foo) {
2225
(self.my_foo, self.my_u8, make_foo())
26+
//[next]~^ ERROR type annotations needed: cannot satisfy `Foo == _`
2327
}
2428
}
2529

‎tests/ui/type-alias-impl-trait/type_of_a_let.stderr renamed to ‎tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0382]: use of moved value: `x`
2-
--> $DIR/type_of_a_let.rs:16:16
2+
--> $DIR/type_of_a_let.rs:20:16
33
|
44
LL | let x: Foo = 22_u32;
55
| - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait
@@ -9,7 +9,7 @@ LL | same_type((x, y));
99
| ^ value used here after move
1010

1111
error[E0382]: use of moved value: `y`
12-
--> $DIR/type_of_a_let.rs:17:6
12+
--> $DIR/type_of_a_let.rs:21:6
1313
|
1414
LL | let y: Foo = x;
1515
| - move occurs because `y` has type `Foo`, which does not implement the `Copy` trait

‎tests/ui/type-alias-impl-trait/type_of_a_let.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// revisions: current next
2+
//[next] compile-flags: -Znext-solver
3+
//[next] check-pass
4+
15
#![feature(type_alias_impl_trait)]
26
#![allow(dead_code)]
37

@@ -13,8 +17,8 @@ fn foo1() -> (u32, Foo) {
1317
fn foo2() -> (u32, Foo) {
1418
let x: Foo = 22_u32;
1519
let y: Foo = x;
16-
same_type((x, y)); //~ ERROR use of moved value
17-
(y, todo!()) //~ ERROR use of moved value
20+
same_type((x, y)); //[current]~ ERROR use of moved value
21+
(y, todo!()) //[current]~ ERROR use of moved value
1822
}
1923

2024
fn same_type<T>(x: (T, T)) {}

0 commit comments

Comments
 (0)
Please sign in to comment.