1
Fork 0

Use can_eq to compare types for default assoc type error

This works correctly with inference variables.
This commit is contained in:
Nilstrieb 2023-01-25 20:11:05 +01:00
parent b222f2e266
commit 943000fdcf
7 changed files with 49 additions and 17 deletions

View file

@ -1850,7 +1850,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
&& let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()
&& let Some(def_id) = def_id.as_local()

View file

@ -515,7 +515,11 @@ fn foo(&tcx) -> Self::T { String::new() }
// `expected` and point at it.
let parent_id = tcx.hir().get_parent_item(hir_id);
let item = tcx.hir().find_by_def_id(parent_id.def_id);
debug!("expected_projection parent item {:?}", item);
let param_env = tcx.param_env(body_owner_def_id);
match item {
Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. })) => {
// FIXME: account for `#![feature(specialization)]`
@ -527,7 +531,8 @@ fn foo(&tcx) -> Self::T { String::new() }
if let hir::Defaultness::Default { has_value: true } =
tcx.impl_defaultness(item.id.owner_id)
{
if tcx.type_of(item.id.owner_id) == found {
let assoc_ty = tcx.bound_type_of(item.id.owner_id).subst_identity();
if self.infcx.can_eq(param_env, assoc_ty, found).is_ok() {
diag.span_label(
item.span,
"associated type defaults can't be assumed inside the \
@ -547,7 +552,9 @@ fn foo(&tcx) -> Self::T { String::new() }
})) => {
for item in &items[..] {
if let hir::AssocItemKind::Type = item.kind {
if tcx.type_of(item.id.owner_id) == found {
let assoc_ty = tcx.bound_type_of(item.id.owner_id).subst_identity();
if self.infcx.can_eq(param_env, assoc_ty, found).is_ok() {
diag.span_label(item.span, "expected this associated type");
return true;
}

View file

@ -441,6 +441,10 @@ impl<'tcx> TyCtxt<'tcx> {
self.opt_def_kind(def_id)
.unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
}
pub fn bound_type_of(self, def_id: impl IntoQueryParam<DefId>) -> ty::EarlyBinder<Ty<'tcx>> {
ty::EarlyBinder(self.type_of(def_id))
}
}
impl<'tcx> TyCtxtAt<'tcx> {
@ -449,4 +453,8 @@ impl<'tcx> TyCtxtAt<'tcx> {
self.opt_def_kind(def_id)
.unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
}
pub fn bound_type_of(self, def_id: impl IntoQueryParam<DefId>) -> ty::EarlyBinder<Ty<'tcx>> {
ty::EarlyBinder(self.type_of(def_id))
}
}

View file

@ -3,7 +3,6 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir;
use crate::ty::layout::IntegerExt;
use crate::ty::query::TyCtxtAt;
use crate::ty::{
self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitable,
@ -637,10 +636,6 @@ impl<'tcx> TyCtxt<'tcx> {
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
}
pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
ty::EarlyBinder(self.type_of(def_id))
}
pub fn bound_return_position_impl_trait_in_trait_tys(
self,
def_id: DefId,
@ -738,12 +733,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
impl<'tcx> TyCtxtAt<'tcx> {
pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
ty::EarlyBinder(self.type_of(def_id))
}
}
struct OpaqueTypeExpander<'tcx> {
// Contains the DefIds of the opaque types that are currently being
// expanded. When we expand an opaque type we insert the DefId of

View file

@ -44,4 +44,18 @@ impl AssocConst for () {
const C: Self::Ty = 0u8;
}
pub trait Trait {
type Res = isize; //~ NOTE associated type defaults can't be assumed inside the trait defining them
fn infer_me_correctly() -> Self::Res {
//~^ NOTE expected `<Self as Trait>::Res` because of return type
// {integer} == isize
2
//~^ ERROR mismatched types
//~| NOTE expected associated type, found integer
//~| NOTE expected associated type `<Self as Trait>::Res`
}
}
fn main() {}

View file

@ -24,6 +24,21 @@ LL | const C: Self::Ty = 0u8;
= note: expected associated type `<Self as AssocConst>::Ty`
found type `u8`
error: aborting due to 2 previous errors
error[E0308]: mismatched types
--> $DIR/defaults-in-other-trait-items.rs:54:9
|
LL | type Res = isize;
| ----------------- associated type defaults can't be assumed inside the trait defining them
LL |
LL | fn infer_me_correctly() -> Self::Res {
| --------- expected `<Self as Trait>::Res` because of return type
...
LL | 2
| ^ expected associated type, found integer
|
= note: expected associated type `<Self as Trait>::Res`
found type `{integer}`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,13 +1,13 @@
error[E0308]: mismatched types
--> $DIR/issue-26681.rs:17:39
|
LL | type Fv: Foo = u8;
| ------------------ associated type defaults can't be assumed inside the trait defining them
LL | const C: <Self::Fv as Foo>::Bar = 6665;
| ^^^^ expected associated type, found integer
|
= note: expected associated type `<<Self as Baz>::Fv as Foo>::Bar`
found type `{integer}`
= help: consider constraining the associated type `<<Self as Baz>::Fv as Foo>::Bar` to `{integer}`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error: aborting due to previous error