mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-10 06:47:34 +00:00
Merge #4950
4950: Use correct substs for super trait assoc types r=matklad a=flodiebold When referring to an associated type of a super trait, we used the substs of the subtrait. That led to the #4931 crash if the subtrait had less parameters, but it could also lead to other incorrectness if just the order was different. Fixes #4931. Co-authored-by: Florian Diebold <florian.diebold@freiheit.com>
This commit is contained in:
commit
1d4388f6bd
@ -337,17 +337,17 @@ impl Ty {
|
|||||||
TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty);
|
TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty);
|
||||||
let ty = if remaining_segments.len() == 1 {
|
let ty = if remaining_segments.len() == 1 {
|
||||||
let segment = remaining_segments.first().unwrap();
|
let segment = remaining_segments.first().unwrap();
|
||||||
let associated_ty = associated_type_by_name_including_super_traits(
|
let found = associated_type_by_name_including_super_traits(
|
||||||
ctx.db.upcast(),
|
ctx.db,
|
||||||
trait_ref.trait_,
|
trait_ref.clone(),
|
||||||
&segment.name,
|
&segment.name,
|
||||||
);
|
);
|
||||||
match associated_ty {
|
match found {
|
||||||
Some(associated_ty) => {
|
Some((super_trait_ref, associated_ty)) => {
|
||||||
// FIXME handle type parameters on the segment
|
// FIXME handle type parameters on the segment
|
||||||
Ty::Projection(ProjectionTy {
|
Ty::Projection(ProjectionTy {
|
||||||
associated_ty,
|
associated_ty,
|
||||||
parameters: trait_ref.substs,
|
parameters: super_trait_ref.substs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@ -706,17 +706,17 @@ fn assoc_type_bindings_from_type_bound<'a>(
|
|||||||
.flat_map(|segment| segment.args_and_bindings.into_iter())
|
.flat_map(|segment| segment.args_and_bindings.into_iter())
|
||||||
.flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
|
.flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
|
||||||
.flat_map(move |binding| {
|
.flat_map(move |binding| {
|
||||||
let associated_ty = associated_type_by_name_including_super_traits(
|
let found = associated_type_by_name_including_super_traits(
|
||||||
ctx.db.upcast(),
|
ctx.db,
|
||||||
trait_ref.trait_,
|
trait_ref.clone(),
|
||||||
&binding.name,
|
&binding.name,
|
||||||
);
|
);
|
||||||
let associated_ty = match associated_ty {
|
let (super_trait_ref, associated_ty) = match found {
|
||||||
None => return SmallVec::<[GenericPredicate; 1]>::new(),
|
None => return SmallVec::<[GenericPredicate; 1]>::new(),
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
};
|
};
|
||||||
let projection_ty =
|
let projection_ty =
|
||||||
ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() };
|
ProjectionTy { associated_ty, parameters: super_trait_ref.substs.clone() };
|
||||||
let mut preds = SmallVec::with_capacity(
|
let mut preds = SmallVec::with_capacity(
|
||||||
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
|
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
|
||||||
);
|
);
|
||||||
|
@ -665,3 +665,31 @@ impl Foo<i64> {
|
|||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_4931() {
|
||||||
|
assert_snapshot!(
|
||||||
|
infer(r#"
|
||||||
|
trait Div<T> {
|
||||||
|
type Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait CheckedDiv: Div<()> {}
|
||||||
|
|
||||||
|
trait PrimInt: CheckedDiv<Output = ()> {
|
||||||
|
fn pow(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check<T: PrimInt>(i: T) {
|
||||||
|
i.pow();
|
||||||
|
}
|
||||||
|
"#),
|
||||||
|
@r###"
|
||||||
|
118..122 'self': Self
|
||||||
|
149..150 'i': T
|
||||||
|
155..171 '{ ...w(); }': ()
|
||||||
|
161..162 'i': T
|
||||||
|
161..168 'i.pow()': ()
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -143,13 +143,14 @@ pub(super) fn find_super_trait_path(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn associated_type_by_name_including_super_traits(
|
pub(super) fn associated_type_by_name_including_super_traits(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn HirDatabase,
|
||||||
trait_: TraitId,
|
trait_ref: TraitRef,
|
||||||
name: &Name,
|
name: &Name,
|
||||||
) -> Option<TypeAliasId> {
|
) -> Option<(TraitRef, TypeAliasId)> {
|
||||||
all_super_traits(db, trait_)
|
all_super_trait_refs(db, trait_ref).into_iter().find_map(|t| {
|
||||||
.into_iter()
|
let assoc_type = db.trait_data(t.trait_).associated_type_by_name(name)?;
|
||||||
.find_map(|t| db.trait_data(t).associated_type_by_name(name))
|
Some((t, assoc_type))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> {
|
pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> {
|
||||||
@ -176,6 +177,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
|
|||||||
Generics { def, params: db.generic_params(def), parent_generics }
|
Generics { def, params: db.generic_params(def), parent_generics }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub(crate) struct Generics {
|
pub(crate) struct Generics {
|
||||||
def: GenericDefId,
|
def: GenericDefId,
|
||||||
pub(crate) params: Arc<GenericParams>,
|
pub(crate) params: Arc<GenericParams>,
|
||||||
|
Loading…
Reference in New Issue
Block a user