9536: Represent opaque types with TyKind::OpaqueType r=flodiebold a=flodiebold

... instead of using `AliasTy`. Chalk turns the alias type into the
placeholder during unification anyway, which confuses our method
resolution logic.

Fixes #9530.

Co-authored-by: Florian Diebold <flodiebold@gmail.com>
This commit is contained in:
bors[bot] 2021-07-08 19:41:03 +00:00 committed by GitHub
commit 80f193e3f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 24 deletions

View File

@ -183,7 +183,7 @@ fn strip_references(&self) -> &Ty {
fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
match self.kind(&Interner) {
TyKind::OpaqueType(opaque_ty_id, ..) => {
TyKind::OpaqueType(opaque_ty_id, subst) => {
match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
let krate = def.module(db.upcast()).krate();
@ -206,7 +206,14 @@ fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereC
None
}
}
ImplTraitId::ReturnTypeImplTrait(..) => None,
ImplTraitId::ReturnTypeImplTrait(func, idx) => {
db.return_type_impl_traits(func).map(|it| {
let data = (*it)
.as_ref()
.map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
data.substitute(&Interner, &subst).into_value_and_skipped_binders().0
})
}
}
}
TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {

View File

@ -384,7 +384,8 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
&TyKind::Alias(AliasTy::Opaque(OpaqueTy {
opaque_ty_id,
substitution: ref parameters,
})) => {
}))
| &TyKind::OpaqueType(opaque_ty_id, ref parameters) => {
let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty_id.into());
if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
datas =

View File

@ -93,7 +93,13 @@ fn debug_alias(
alias: &chalk_ir::AliasTy<Interner>,
fmt: &mut fmt::Formatter<'_>,
) -> Option<fmt::Result> {
tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt)))
use std::fmt::Debug;
match alias {
chalk_ir::AliasTy::Projection(projection_ty) => {
Interner::debug_projection_ty(projection_ty, fmt)
}
chalk_ir::AliasTy::Opaque(opaque_ty) => Some(opaque_ty.fmt(fmt)),
}
}
fn debug_projection_ty(
@ -114,7 +120,7 @@ fn debug_opaque_ty_id(
opaque_ty_id: chalk_ir::OpaqueTyId<Self>,
fmt: &mut fmt::Formatter<'_>,
) -> Option<fmt::Result> {
Some(fmt.debug_struct("OpaqueTyId").field("index", &opaque_ty_id.0).finish())
Some(write!(fmt, "OpaqueTy#{}", opaque_ty_id.0))
}
fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {

View File

@ -38,7 +38,7 @@
all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics,
},
AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig,
FnSubst, ImplTraitId, Interner, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
FnSubst, ImplTraitId, Interner, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution,
TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
};
@ -250,11 +250,7 @@ pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
let generics = generics(self.db.upcast(), func.into());
let parameters = generics.bound_vars_subst(self.in_binders);
TyKind::Alias(AliasTy::Opaque(OpaqueTy {
opaque_ty_id,
substitution: parameters,
}))
.intern(&Interner)
TyKind::OpaqueType(opaque_ty_id, parameters).intern(&Interner)
}
ImplTraitLoweringMode::Param => {
let idx = self.impl_trait_counter.get();

View File

@ -1058,3 +1058,22 @@ fn no_actual_tail(){
"#]],
)
}
#[test]
fn impl_trait_in_option_9530() {
check_types(
r#"
struct Option<T>;
impl<T> Option<T> {
fn unwrap(self) -> T { loop {} }
}
fn make() -> Option<impl Copy> { Option }
trait Copy {}
fn test() {
let o = make();
o.unwrap();
//^^^^^^^^^^ impl Copy
}
"#,
)
}

View File

@ -1,7 +1,6 @@
//! Implementation of Chalk debug helper functions using TLS.
use std::fmt::{self, Debug};
use std::fmt;
use chalk_ir::AliasTy;
use itertools::Itertools;
use crate::{
@ -53,17 +52,6 @@ pub(crate) fn debug_assoc_type_id(
write!(fmt, "{}::{}", trait_data.name, type_alias_data.name)
}
pub(crate) fn debug_alias(
&self,
alias_ty: &AliasTy<Interner>,
fmt: &mut fmt::Formatter<'_>,
) -> Result<(), fmt::Error> {
match alias_ty {
AliasTy::Projection(projection_ty) => self.debug_projection_ty(projection_ty, fmt),
AliasTy::Opaque(opaque_ty) => opaque_ty.fmt(fmt),
}
}
pub(crate) fn debug_projection_ty(
&self,
projection_ty: &chalk_ir::ProjectionTy<Interner>,