Use can_eq
to compare types for default assoc type error
This works correctly with inference variables.
This commit is contained in:
parent
b222f2e266
commit
943000fdcf
7 changed files with 49 additions and 17 deletions
|
@ -1850,7 +1850,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
|
|
||||||
self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
|
self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
|
||||||
|
|
||||||
|
|
||||||
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
|
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
|
||||||
&& let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()
|
&& let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()
|
||||||
&& let Some(def_id) = def_id.as_local()
|
&& let Some(def_id) = def_id.as_local()
|
||||||
|
|
|
@ -515,7 +515,11 @@ fn foo(&tcx) -> Self::T { String::new() }
|
||||||
// `expected` and point at it.
|
// `expected` and point at it.
|
||||||
let parent_id = tcx.hir().get_parent_item(hir_id);
|
let parent_id = tcx.hir().get_parent_item(hir_id);
|
||||||
let item = tcx.hir().find_by_def_id(parent_id.def_id);
|
let item = tcx.hir().find_by_def_id(parent_id.def_id);
|
||||||
|
|
||||||
debug!("expected_projection parent item {:?}", item);
|
debug!("expected_projection parent item {:?}", item);
|
||||||
|
|
||||||
|
let param_env = tcx.param_env(body_owner_def_id);
|
||||||
|
|
||||||
match item {
|
match item {
|
||||||
Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. })) => {
|
Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. })) => {
|
||||||
// FIXME: account for `#![feature(specialization)]`
|
// FIXME: account for `#![feature(specialization)]`
|
||||||
|
@ -527,7 +531,8 @@ fn foo(&tcx) -> Self::T { String::new() }
|
||||||
if let hir::Defaultness::Default { has_value: true } =
|
if let hir::Defaultness::Default { has_value: true } =
|
||||||
tcx.impl_defaultness(item.id.owner_id)
|
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(
|
diag.span_label(
|
||||||
item.span,
|
item.span,
|
||||||
"associated type defaults can't be assumed inside the \
|
"associated type defaults can't be assumed inside the \
|
||||||
|
@ -547,7 +552,9 @@ fn foo(&tcx) -> Self::T { String::new() }
|
||||||
})) => {
|
})) => {
|
||||||
for item in &items[..] {
|
for item in &items[..] {
|
||||||
if let hir::AssocItemKind::Type = item.kind {
|
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");
|
diag.span_label(item.span, "expected this associated type");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -441,6 +441,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self.opt_def_kind(def_id)
|
self.opt_def_kind(def_id)
|
||||||
.unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", 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> {
|
impl<'tcx> TyCtxtAt<'tcx> {
|
||||||
|
@ -449,4 +453,8 @@ impl<'tcx> TyCtxtAt<'tcx> {
|
||||||
self.opt_def_kind(def_id)
|
self.opt_def_kind(def_id)
|
||||||
.unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", 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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||||
use crate::mir;
|
use crate::mir;
|
||||||
use crate::ty::layout::IntegerExt;
|
use crate::ty::layout::IntegerExt;
|
||||||
use crate::ty::query::TyCtxtAt;
|
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||||
TypeVisitable,
|
TypeVisitable,
|
||||||
|
@ -637,10 +636,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
|
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(
|
pub fn bound_return_position_impl_trait_in_trait_tys(
|
||||||
self,
|
self,
|
||||||
def_id: DefId,
|
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> {
|
struct OpaqueTypeExpander<'tcx> {
|
||||||
// Contains the DefIds of the opaque types that are currently being
|
// Contains the DefIds of the opaque types that are currently being
|
||||||
// expanded. When we expand an opaque type we insert the DefId of
|
// expanded. When we expand an opaque type we insert the DefId of
|
||||||
|
|
|
@ -44,4 +44,18 @@ impl AssocConst for () {
|
||||||
const C: Self::Ty = 0u8;
|
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() {}
|
fn main() {}
|
||||||
|
|
|
@ -24,6 +24,21 @@ LL | const C: Self::Ty = 0u8;
|
||||||
= note: expected associated type `<Self as AssocConst>::Ty`
|
= note: expected associated type `<Self as AssocConst>::Ty`
|
||||||
found type `u8`
|
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`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-26681.rs:17:39
|
--> $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;
|
LL | const C: <Self::Fv as Foo>::Bar = 6665;
|
||||||
| ^^^^ expected associated type, found integer
|
| ^^^^ expected associated type, found integer
|
||||||
|
|
|
|
||||||
= note: expected associated type `<<Self as Baz>::Fv as Foo>::Bar`
|
= note: expected associated type `<<Self as Baz>::Fv as Foo>::Bar`
|
||||||
found type `{integer}`
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue