Skip to content

Commit

Permalink
Teach MIR borrowck how to deal with default body RPITITs
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jan 17, 2023
1 parent 9f76362 commit 52d847b
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
20 changes: 19 additions & 1 deletion compiler/rustc_borrowck/src/type_check/input_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
//! contain revealed `impl Trait` values).
use rustc_hir::def::DefKind;
use rustc_index::vec::Idx;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty};
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_span::Span;

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

#[instrument(skip(self), level = "debug")]
fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
let (a, b) = (a, b).fold_with(&mut BottomUpFolder {
tcx: self.infcx.tcx,
ty_op: |ty| {
if let ty::Alias(ty::Projection, ty::AliasTy { def_id, substs, .. }) = *ty.kind()
&& self.infcx.tcx.def_kind(def_id) == DefKind::ImplTraitPlaceholder
&& def_id.as_local().map_or(false, |def_id| self.infcx.opaque_type_origin(def_id, span).is_some())
{
self.infcx.tcx.mk_opaque(def_id, substs)
} else {
ty
}
},
lt_op: |lt| lt,
ct_op: |ct| ct,
});

if let Err(_) =
self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
{
Expand Down
39 changes: 38 additions & 1 deletion compiler/rustc_infer/src/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::infer::{ConstVarValue, ConstVariableValue};
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::traits::{Obligation, PredicateObligation};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::DefKind;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
Expand Down Expand Up @@ -410,7 +411,7 @@ where
let (a, b) = match (a.kind(), b.kind()) {
(&ty::Alias(ty::Opaque, ..), _) => (a, generalize(b, false)?),
(_, &ty::Alias(ty::Opaque, ..)) => (generalize(a, true)?, b),
_ => unreachable!(),
_ => unreachable!("expected an opaque, got {a} and {b}"),
};
let cause = ObligationCause::dummy_with_span(self.delegate.span());
let obligations = self
Expand Down Expand Up @@ -627,6 +628,42 @@ where
self.relate_opaques(a, b)
}

// Handle default-body RPITITs
(
&ty::Alias(ty::Projection, ty::AliasTy { def_id: a_def_id, .. }),
&ty::Alias(ty::Projection, ty::AliasTy { def_id: b_def_id, .. }),
) if a_def_id == b_def_id
&& self.tcx().def_kind(a_def_id) == DefKind::ImplTraitPlaceholder
&& a_def_id.as_local().map_or(false, |def_id| {
self.infcx.opaque_type_origin(def_id, self.delegate.span()).is_some()
}) =>
{
infcx.super_combine_tys(self, a, b).or_else(|err| {
self.tcx().sess.delay_span_bug(
self.delegate.span(),
"failure to relate an opaque to itself should result in an error later on",
);
if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
})
}
(&ty::Alias(ty::Projection, ty::AliasTy { def_id, substs, .. }), _)
if self.tcx().def_kind(def_id) == DefKind::ImplTraitPlaceholder
&& def_id.as_local().map_or(false, |def_id| {
self.infcx.opaque_type_origin(def_id, self.delegate.span()).is_some()
}) =>
{
self.relate_opaques(self.tcx().mk_opaque(def_id, substs), b)
}

(_, &ty::Alias(ty::Projection, ty::AliasTy { def_id, substs, .. }))
if self.tcx().def_kind(def_id) == DefKind::ImplTraitPlaceholder
&& def_id.as_local().map_or(false, |def_id| {
self.infcx.opaque_type_origin(def_id, self.delegate.span()).is_some()
}) =>
{
self.relate_opaques(a, self.tcx().mk_opaque(def_id, substs))
}

(&ty::Alias(ty::Projection, projection_ty), _)
if D::normalization() == NormalizationStrategy::Lazy =>
{
Expand Down
3 changes: 0 additions & 3 deletions tests/ui/impl-trait/in-trait/default-body-type-err.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
|
LL | fn lol(&self) -> impl Deref<Target = String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
LL |
LL | &1i32
| ----- return type was inferred to be `&i32` here

error: aborting due to previous error

Expand Down

0 comments on commit 52d847b

Please sign in to comment.