Skip to content

Commit 52d847b

Browse files
Teach MIR borrowck how to deal with default body RPITITs
1 parent 9f76362 commit 52d847b

File tree

3 files changed

+57
-5
lines changed

3 files changed

+57
-5
lines changed

compiler/rustc_borrowck/src/type_check/input_output.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
88
//! contain revealed `impl Trait` values).
99
10+
use rustc_hir::def::DefKind;
1011
use rustc_index::vec::Idx;
1112
use rustc_infer::infer::LateBoundRegionConversionTime;
1213
use rustc_middle::mir::*;
13-
use rustc_middle::ty::{self, Ty};
14+
use rustc_middle::ty::fold::BottomUpFolder;
15+
use rustc_middle::ty::{self, Ty, TypeFoldable};
1416
use rustc_span::Span;
1517

1618
use crate::universal_regions::UniversalRegions;
@@ -148,6 +150,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
148150

149151
#[instrument(skip(self), level = "debug")]
150152
fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
153+
let (a, b) = (a, b).fold_with(&mut BottomUpFolder {
154+
tcx: self.infcx.tcx,
155+
ty_op: |ty| {
156+
if let ty::Alias(ty::Projection, ty::AliasTy { def_id, substs, .. }) = *ty.kind()
157+
&& self.infcx.tcx.def_kind(def_id) == DefKind::ImplTraitPlaceholder
158+
&& def_id.as_local().map_or(false, |def_id| self.infcx.opaque_type_origin(def_id, span).is_some())
159+
{
160+
self.infcx.tcx.mk_opaque(def_id, substs)
161+
} else {
162+
ty
163+
}
164+
},
165+
lt_op: |lt| lt,
166+
ct_op: |ct| ct,
167+
});
168+
151169
if let Err(_) =
152170
self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
153171
{

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

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use crate::infer::{ConstVarValue, ConstVariableValue};
2727
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
2828
use crate::traits::{Obligation, PredicateObligation};
2929
use rustc_data_structures::fx::FxHashMap;
30+
use rustc_hir::def::DefKind;
3031
use rustc_middle::traits::ObligationCause;
3132
use rustc_middle::ty::error::TypeError;
3233
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
@@ -410,7 +411,7 @@ where
410411
let (a, b) = match (a.kind(), b.kind()) {
411412
(&ty::Alias(ty::Opaque, ..), _) => (a, generalize(b, false)?),
412413
(_, &ty::Alias(ty::Opaque, ..)) => (generalize(a, true)?, b),
413-
_ => unreachable!(),
414+
_ => unreachable!("expected an opaque, got {a} and {b}"),
414415
};
415416
let cause = ObligationCause::dummy_with_span(self.delegate.span());
416417
let obligations = self
@@ -627,6 +628,42 @@ where
627628
self.relate_opaques(a, b)
628629
}
629630

631+
// Handle default-body RPITITs
632+
(
633+
&ty::Alias(ty::Projection, ty::AliasTy { def_id: a_def_id, .. }),
634+
&ty::Alias(ty::Projection, ty::AliasTy { def_id: b_def_id, .. }),
635+
) if a_def_id == b_def_id
636+
&& self.tcx().def_kind(a_def_id) == DefKind::ImplTraitPlaceholder
637+
&& a_def_id.as_local().map_or(false, |def_id| {
638+
self.infcx.opaque_type_origin(def_id, self.delegate.span()).is_some()
639+
}) =>
640+
{
641+
infcx.super_combine_tys(self, a, b).or_else(|err| {
642+
self.tcx().sess.delay_span_bug(
643+
self.delegate.span(),
644+
"failure to relate an opaque to itself should result in an error later on",
645+
);
646+
if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
647+
})
648+
}
649+
(&ty::Alias(ty::Projection, ty::AliasTy { def_id, substs, .. }), _)
650+
if self.tcx().def_kind(def_id) == DefKind::ImplTraitPlaceholder
651+
&& def_id.as_local().map_or(false, |def_id| {
652+
self.infcx.opaque_type_origin(def_id, self.delegate.span()).is_some()
653+
}) =>
654+
{
655+
self.relate_opaques(self.tcx().mk_opaque(def_id, substs), b)
656+
}
657+
658+
(_, &ty::Alias(ty::Projection, ty::AliasTy { def_id, substs, .. }))
659+
if self.tcx().def_kind(def_id) == DefKind::ImplTraitPlaceholder
660+
&& def_id.as_local().map_or(false, |def_id| {
661+
self.infcx.opaque_type_origin(def_id, self.delegate.span()).is_some()
662+
}) =>
663+
{
664+
self.relate_opaques(a, self.tcx().mk_opaque(def_id, substs))
665+
}
666+
630667
(&ty::Alias(ty::Projection, projection_ty), _)
631668
if D::normalization() == NormalizationStrategy::Lazy =>
632669
{

tests/ui/impl-trait/in-trait/default-body-type-err.stderr

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
33
|
44
LL | fn lol(&self) -> impl Deref<Target = String> {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
6-
LL |
7-
LL | &1i32
8-
| ----- return type was inferred to be `&i32` here
96

107
error: aborting due to previous error
118

0 commit comments

Comments
 (0)