Skip to content

Commit f3a1901

Browse files
authored
Unrolled build for rust-lang#130866
Rollup merge of rust-lang#130866 - compiler-errors:dyn-instantiate-binder, r=lcnr Allow instantiating object trait binder when upcasting This PR fixes two bugs (that probably need an FCP). ### We use equality rather than subtyping for upcasting dyn conversions This code should be valid: ```rust #![feature(trait_upcasting)] trait Foo: for<'h> Bar<'h> {} trait Bar<'a> {} fn foo(x: &dyn Foo) { let y: &dyn Bar<'static> = x; } ``` But instead: ``` error[E0308]: mismatched types --> src/lib.rs:7:32 | 7 | let y: &dyn Bar<'static> = x; | ^ one type is more general than the other | = note: expected existential trait ref `for<'h> Bar<'h>` found existential trait ref `Bar<'_>` ``` And so should this: ```rust #![feature(trait_upcasting)] fn foo(x: &dyn for<'h> Fn(&'h ())) { let y: &dyn FnOnce(&'static ()) = x; } ``` But instead: ``` error[E0308]: mismatched types --> src/lib.rs:4:39 | 4 | let y: &dyn FnOnce(&'static ()) = x; | ^ one type is more general than the other | = note: expected existential trait ref `for<'h> FnOnce<(&'h (),)>` found existential trait ref `FnOnce<(&(),)>` ``` Specifically, both of these fail because we use *equality* when comparing the supertrait to the *target* of the unsize goal. For the first example, since our supertrait is `for<'h> Bar<'h>` but our target is `Bar<'static>`, there's a higher-ranked type mismatch even though we *should* be able to instantiate that supertrait binder when upcasting. Similarly for the second example. ### New solver uses equality rather than subtyping for no-op (i.e. non-upcasting) dyn conversions This code should be valid in the new solver, like it is with the old solver: ```rust // -Znext-solver fn foo<'a>(x: &mut for<'h> dyn Fn(&'h ())) { let _: &mut dyn Fn(&'a ()) = x; } ``` But instead: ``` error: lifetime may not live long enough --> <source>:2:11 | 1 | fn foo<'a>(x: &mut dyn for<'h> Fn(&'h ())) { | -- lifetime `'a` defined here 2 | let _: &mut dyn Fn(&'a ()) = x; | ^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` | = note: requirement occurs because of a mutable reference to `dyn Fn(&())` ``` Specifically, this fails because we try to coerce `&mut dyn for<'h> Fn(&'h ())` to `&mut dyn Fn(&'a ())`, which registers an `dyn for<'h> Fn(&'h ()): dyn Fn(&'a ())` goal. This fails because the new solver uses *equating* rather than *subtyping* in `Unsize` goals. This is *mostly* not a problem... You may wonder why the same code passes on the new solver for immutable references: ``` // -Znext-solver fn foo<'a>(x: &dyn Fn(&())) { let _: &dyn Fn(&'a ()) = x; // works } ``` That's because in this case, we first try to coerce via `Unsize`, but due to the leak check the goal fails. Then, later in coercion, we fall back to a simple subtyping operation, which *does* work. Since `&T` is covariant over `T`, but `&mut T` is invariant, that's where the discrepancy between these two examples crops up. --- r? lcnr or reassign :D
2 parents 150247c + d753aba commit f3a1901

File tree

10 files changed

+228
-201
lines changed

10 files changed

+228
-201
lines changed

compiler/rustc_infer/src/infer/at.rs

+54-110
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,7 @@ impl<'tcx> InferCtxt<'tcx> {
9292
}
9393

9494
pub trait ToTrace<'tcx>: Relate<TyCtxt<'tcx>> + Copy {
95-
fn to_trace(
96-
cause: &ObligationCause<'tcx>,
97-
a_is_expected: bool,
98-
a: Self,
99-
b: Self,
100-
) -> TypeTrace<'tcx>;
95+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx>;
10196
}
10297

10398
impl<'a, 'tcx> At<'a, 'tcx> {
@@ -116,7 +111,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
116111
{
117112
let mut fields = CombineFields::new(
118113
self.infcx,
119-
ToTrace::to_trace(self.cause, true, expected, actual),
114+
ToTrace::to_trace(self.cause, expected, actual),
120115
self.param_env,
121116
define_opaque_types,
122117
);
@@ -136,7 +131,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
136131
{
137132
let mut fields = CombineFields::new(
138133
self.infcx,
139-
ToTrace::to_trace(self.cause, true, expected, actual),
134+
ToTrace::to_trace(self.cause, expected, actual),
140135
self.param_env,
141136
define_opaque_types,
142137
);
@@ -154,12 +149,26 @@ impl<'a, 'tcx> At<'a, 'tcx> {
154149
where
155150
T: ToTrace<'tcx>,
156151
{
157-
let mut fields = CombineFields::new(
158-
self.infcx,
159-
ToTrace::to_trace(self.cause, true, expected, actual),
160-
self.param_env,
152+
self.eq_trace(
161153
define_opaque_types,
162-
);
154+
ToTrace::to_trace(self.cause, expected, actual),
155+
expected,
156+
actual,
157+
)
158+
}
159+
160+
/// Makes `expected == actual`.
161+
pub fn eq_trace<T>(
162+
self,
163+
define_opaque_types: DefineOpaqueTypes,
164+
trace: TypeTrace<'tcx>,
165+
expected: T,
166+
actual: T,
167+
) -> InferResult<'tcx, ()>
168+
where
169+
T: Relate<TyCtxt<'tcx>>,
170+
{
171+
let mut fields = CombineFields::new(self.infcx, trace, self.param_env, define_opaque_types);
163172
fields.equate(StructurallyRelateAliases::No).relate(expected, actual)?;
164173
Ok(InferOk {
165174
value: (),
@@ -192,7 +201,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
192201
assert!(self.infcx.next_trait_solver());
193202
let mut fields = CombineFields::new(
194203
self.infcx,
195-
ToTrace::to_trace(self.cause, true, expected, actual),
204+
ToTrace::to_trace(self.cause, expected, actual),
196205
self.param_env,
197206
DefineOpaqueTypes::Yes,
198207
);
@@ -284,7 +293,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
284293
{
285294
let mut fields = CombineFields::new(
286295
self.infcx,
287-
ToTrace::to_trace(self.cause, true, expected, actual),
296+
ToTrace::to_trace(self.cause, expected, actual),
288297
self.param_env,
289298
define_opaque_types,
290299
);
@@ -306,7 +315,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
306315
{
307316
let mut fields = CombineFields::new(
308317
self.infcx,
309-
ToTrace::to_trace(self.cause, true, expected, actual),
318+
ToTrace::to_trace(self.cause, expected, actual),
310319
self.param_env,
311320
define_opaque_types,
312321
);
@@ -316,18 +325,13 @@ impl<'a, 'tcx> At<'a, 'tcx> {
316325
}
317326

318327
impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> {
319-
fn to_trace(
320-
cause: &ObligationCause<'tcx>,
321-
a_is_expected: bool,
322-
a: Self,
323-
b: Self,
324-
) -> TypeTrace<'tcx> {
328+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
325329
match (a, b) {
326330
(ImplSubject::Trait(trait_ref_a), ImplSubject::Trait(trait_ref_b)) => {
327-
ToTrace::to_trace(cause, a_is_expected, trait_ref_a, trait_ref_b)
331+
ToTrace::to_trace(cause, trait_ref_a, trait_ref_b)
328332
}
329333
(ImplSubject::Inherent(ty_a), ImplSubject::Inherent(ty_b)) => {
330-
ToTrace::to_trace(cause, a_is_expected, ty_a, ty_b)
334+
ToTrace::to_trace(cause, ty_a, ty_b)
331335
}
332336
(ImplSubject::Trait(_), ImplSubject::Inherent(_))
333337
| (ImplSubject::Inherent(_), ImplSubject::Trait(_)) => {
@@ -338,65 +342,45 @@ impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> {
338342
}
339343

340344
impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
341-
fn to_trace(
342-
cause: &ObligationCause<'tcx>,
343-
a_is_expected: bool,
344-
a: Self,
345-
b: Self,
346-
) -> TypeTrace<'tcx> {
345+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
347346
TypeTrace {
348347
cause: cause.clone(),
349-
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
348+
values: ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())),
350349
}
351350
}
352351
}
353352

354353
impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
355-
fn to_trace(
356-
cause: &ObligationCause<'tcx>,
357-
a_is_expected: bool,
358-
a: Self,
359-
b: Self,
360-
) -> TypeTrace<'tcx> {
354+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
361355
TypeTrace {
362356
cause: cause.clone(),
363-
values: ValuePairs::Regions(ExpectedFound::new(a_is_expected, a, b)),
357+
values: ValuePairs::Regions(ExpectedFound::new(true, a, b)),
364358
}
365359
}
366360
}
367361

368362
impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
369-
fn to_trace(
370-
cause: &ObligationCause<'tcx>,
371-
a_is_expected: bool,
372-
a: Self,
373-
b: Self,
374-
) -> TypeTrace<'tcx> {
363+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
375364
TypeTrace {
376365
cause: cause.clone(),
377-
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
366+
values: ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())),
378367
}
379368
}
380369
}
381370

382371
impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
383-
fn to_trace(
384-
cause: &ObligationCause<'tcx>,
385-
a_is_expected: bool,
386-
a: Self,
387-
b: Self,
388-
) -> TypeTrace<'tcx> {
372+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
389373
TypeTrace {
390374
cause: cause.clone(),
391375
values: match (a.unpack(), b.unpack()) {
392376
(GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => {
393-
ValuePairs::Regions(ExpectedFound::new(a_is_expected, a, b))
377+
ValuePairs::Regions(ExpectedFound::new(true, a, b))
394378
}
395379
(GenericArgKind::Type(a), GenericArgKind::Type(b)) => {
396-
ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
380+
ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into()))
397381
}
398382
(GenericArgKind::Const(a), GenericArgKind::Const(b)) => {
399-
ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
383+
ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into()))
400384
}
401385

402386
(
@@ -419,72 +403,47 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
419403
}
420404

421405
impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
422-
fn to_trace(
423-
cause: &ObligationCause<'tcx>,
424-
a_is_expected: bool,
425-
a: Self,
426-
b: Self,
427-
) -> TypeTrace<'tcx> {
406+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
428407
TypeTrace {
429408
cause: cause.clone(),
430-
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a, b)),
409+
values: ValuePairs::Terms(ExpectedFound::new(true, a, b)),
431410
}
432411
}
433412
}
434413

435414
impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
436-
fn to_trace(
437-
cause: &ObligationCause<'tcx>,
438-
a_is_expected: bool,
439-
a: Self,
440-
b: Self,
441-
) -> TypeTrace<'tcx> {
415+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
442416
TypeTrace {
443417
cause: cause.clone(),
444-
values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
418+
values: ValuePairs::TraitRefs(ExpectedFound::new(true, a, b)),
445419
}
446420
}
447421
}
448422

449423
impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
450-
fn to_trace(
451-
cause: &ObligationCause<'tcx>,
452-
a_is_expected: bool,
453-
a: Self,
454-
b: Self,
455-
) -> TypeTrace<'tcx> {
424+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
456425
TypeTrace {
457426
cause: cause.clone(),
458-
values: ValuePairs::Aliases(ExpectedFound::new(a_is_expected, a.into(), b.into())),
427+
values: ValuePairs::Aliases(ExpectedFound::new(true, a.into(), b.into())),
459428
}
460429
}
461430
}
462431

463432
impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> {
464-
fn to_trace(
465-
cause: &ObligationCause<'tcx>,
466-
a_is_expected: bool,
467-
a: Self,
468-
b: Self,
469-
) -> TypeTrace<'tcx> {
433+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
470434
TypeTrace {
471435
cause: cause.clone(),
472-
values: ValuePairs::Aliases(ExpectedFound::new(a_is_expected, a, b)),
436+
values: ValuePairs::Aliases(ExpectedFound::new(true, a, b)),
473437
}
474438
}
475439
}
476440

477441
impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
478-
fn to_trace(
479-
cause: &ObligationCause<'tcx>,
480-
a_is_expected: bool,
481-
a: Self,
482-
b: Self,
483-
) -> TypeTrace<'tcx> {
442+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
484443
TypeTrace {
485444
cause: cause.clone(),
486445
values: ValuePairs::PolySigs(ExpectedFound::new(
487-
a_is_expected,
446+
true,
488447
ty::Binder::dummy(a),
489448
ty::Binder::dummy(b),
490449
)),
@@ -493,43 +452,28 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
493452
}
494453

495454
impl<'tcx> ToTrace<'tcx> for ty::PolyFnSig<'tcx> {
496-
fn to_trace(
497-
cause: &ObligationCause<'tcx>,
498-
a_is_expected: bool,
499-
a: Self,
500-
b: Self,
501-
) -> TypeTrace<'tcx> {
455+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
502456
TypeTrace {
503457
cause: cause.clone(),
504-
values: ValuePairs::PolySigs(ExpectedFound::new(a_is_expected, a, b)),
458+
values: ValuePairs::PolySigs(ExpectedFound::new(true, a, b)),
505459
}
506460
}
507461
}
508462

509463
impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> {
510-
fn to_trace(
511-
cause: &ObligationCause<'tcx>,
512-
a_is_expected: bool,
513-
a: Self,
514-
b: Self,
515-
) -> TypeTrace<'tcx> {
464+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
516465
TypeTrace {
517466
cause: cause.clone(),
518-
values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(a_is_expected, a, b)),
467+
values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(true, a, b)),
519468
}
520469
}
521470
}
522471

523472
impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
524-
fn to_trace(
525-
cause: &ObligationCause<'tcx>,
526-
a_is_expected: bool,
527-
a: Self,
528-
b: Self,
529-
) -> TypeTrace<'tcx> {
473+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
530474
TypeTrace {
531475
cause: cause.clone(),
532-
values: ValuePairs::ExistentialProjection(ExpectedFound::new(a_is_expected, a, b)),
476+
values: ValuePairs::ExistentialProjection(ExpectedFound::new(true, a, b)),
533477
}
534478
}
535479
}

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

+9-7
Original file line numberDiff line numberDiff line change
@@ -448,10 +448,10 @@ where
448448
}
449449
}
450450
} else {
451-
self.delegate.enter_forall(kind, |kind| {
452-
let goal = goal.with(self.cx(), ty::Binder::dummy(kind));
453-
self.add_goal(GoalSource::InstantiateHigherRanked, goal);
454-
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
451+
self.enter_forall(kind, |ecx, kind| {
452+
let goal = goal.with(ecx.cx(), ty::Binder::dummy(kind));
453+
ecx.add_goal(GoalSource::InstantiateHigherRanked, goal);
454+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
455455
})
456456
}
457457
}
@@ -840,12 +840,14 @@ where
840840
self.delegate.instantiate_binder_with_infer(value)
841841
}
842842

843+
/// `enter_forall`, but takes `&mut self` and passes it back through the
844+
/// callback since it can't be aliased during the call.
843845
pub(super) fn enter_forall<T: TypeFoldable<I> + Copy, U>(
844-
&self,
846+
&mut self,
845847
value: ty::Binder<I, T>,
846-
f: impl FnOnce(T) -> U,
848+
f: impl FnOnce(&mut Self, T) -> U,
847849
) -> U {
848-
self.delegate.enter_forall(value, f)
850+
self.delegate.enter_forall(value, |value| f(self, value))
849851
}
850852

851853
pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T

0 commit comments

Comments
 (0)