Represent opaque types with TyKind::OpaqueType

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

Fixes #9530.
This commit is contained in:
Florian Diebold 2021-07-08 21:19:53 +02:00
parent 552b50de9e
commit d674d7185d
6 changed files with 41 additions and 24 deletions

View file

@ -183,7 +183,7 @@ impl TyExt for Ty {
fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> { fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
match self.kind(&Interner) { 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()) { match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => { ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
let krate = def.module(db.upcast()).krate(); let krate = def.module(db.upcast()).krate();
@ -206,7 +206,14 @@ impl TyExt for Ty {
None 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)) => { TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {

View file

@ -384,7 +384,8 @@ impl HirDisplay for Ty {
&TyKind::Alias(AliasTy::Opaque(OpaqueTy { &TyKind::Alias(AliasTy::Opaque(OpaqueTy {
opaque_ty_id, opaque_ty_id,
substitution: ref parameters, 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()); let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty_id.into());
if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id { if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
datas = datas =

View file

@ -93,7 +93,13 @@ impl chalk_ir::interner::Interner for Interner {
alias: &chalk_ir::AliasTy<Interner>, alias: &chalk_ir::AliasTy<Interner>,
fmt: &mut fmt::Formatter<'_>, fmt: &mut fmt::Formatter<'_>,
) -> Option<fmt::Result> { ) -> 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( fn debug_projection_ty(
@ -114,7 +120,7 @@ impl chalk_ir::interner::Interner for Interner {
opaque_ty_id: chalk_ir::OpaqueTyId<Self>, opaque_ty_id: chalk_ir::OpaqueTyId<Self>,
fmt: &mut fmt::Formatter<'_>, fmt: &mut fmt::Formatter<'_>,
) -> Option<fmt::Result> { ) -> 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> { fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {

View file

@ -38,7 +38,7 @@ use crate::{
all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics, all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics,
}, },
AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, 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, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution,
TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
}; };
@ -250,11 +250,7 @@ impl<'a> TyLoweringContext<'a> {
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
let generics = generics(self.db.upcast(), func.into()); let generics = generics(self.db.upcast(), func.into());
let parameters = generics.bound_vars_subst(self.in_binders); let parameters = generics.bound_vars_subst(self.in_binders);
TyKind::Alias(AliasTy::Opaque(OpaqueTy { TyKind::OpaqueType(opaque_ty_id, parameters).intern(&Interner)
opaque_ty_id,
substitution: parameters,
}))
.intern(&Interner)
} }
ImplTraitLoweringMode::Param => { ImplTraitLoweringMode::Param => {
let idx = self.impl_trait_counter.get(); let idx = self.impl_trait_counter.get();

View file

@ -1058,3 +1058,22 @@ fn cfg_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. //! Implementation of Chalk debug helper functions using TLS.
use std::fmt::{self, Debug}; use std::fmt;
use chalk_ir::AliasTy;
use itertools::Itertools; use itertools::Itertools;
use crate::{ use crate::{
@ -53,17 +52,6 @@ impl DebugContext<'_> {
write!(fmt, "{}::{}", trait_data.name, type_alias_data.name) 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( pub(crate) fn debug_projection_ty(
&self, &self,
projection_ty: &chalk_ir::ProjectionTy<Interner>, projection_ty: &chalk_ir::ProjectionTy<Interner>,