error message

This commit is contained in:
Douglas Creager 2025-12-15 14:38:54 -05:00
parent 9b5709f34b
commit d94b2d3578
2 changed files with 62 additions and 19 deletions

View File

@ -4445,7 +4445,6 @@ impl<'db> BindingError<'db> {
return;
};
let typevar = error.bound_typevar().typevar(context.db());
let argument_type = error.argument_type();
let argument_ty_display = argument_type.display(context.db());
@ -4458,21 +4457,51 @@ impl<'db> BindingError<'db> {
}
));
let typevar_name = typevar.name(context.db());
match error {
SpecializationError::MismatchedBound { .. } => {
diag.set_primary_message(format_args!("Argument type `{argument_ty_display}` does not satisfy upper bound `{}` of type variable `{typevar_name}`",
typevar.upper_bound(context.db()).expect("type variable should have an upper bound if this error occurs").display(context.db())
SpecializationError::NoSolution { parameter, .. } => {
diag.set_primary_message(format_args!(
"Argument type `{argument_ty_display}` does not \
satisfy generic parameter annotation `{}",
parameter.display(context.db()),
));
}
SpecializationError::MismatchedConstraint { .. } => {
diag.set_primary_message(format_args!("Argument type `{argument_ty_display}` does not satisfy constraints ({}) of type variable `{typevar_name}`",
typevar.constraints(context.db()).expect("type variable should have constraints if this error occurs").iter().map(|ty| format!("`{}`", ty.display(context.db()))).join(", ")
SpecializationError::MismatchedBound { bound_typevar, .. } => {
let typevar = bound_typevar.typevar(context.db());
let typevar_name = typevar.name(context.db());
diag.set_primary_message(format_args!(
"Argument type `{argument_ty_display}` does not \
satisfy upper bound `{}` of type variable `{typevar_name}`",
typevar
.upper_bound(context.db())
.expect(
"type variable should have an upper bound if this error occurs"
)
.display(context.db())
));
}
SpecializationError::MismatchedConstraint { bound_typevar, .. } => {
let typevar = bound_typevar.typevar(context.db());
let typevar_name = typevar.name(context.db());
diag.set_primary_message(format_args!(
"Argument type `{argument_ty_display}` does not \
satisfy constraints ({}) of type variable `{typevar_name}`",
typevar
.constraints(context.db())
.expect(
"type variable should have constraints if this error occurs"
)
.iter()
.format_with(", ", |ty, f| f(&format_args!(
"`{}`",
ty.display(context.db())
)))
));
}
}
if let Some(typevar_definition) = typevar.definition(context.db()) {
if let Some(typevar_definition) = error.bound_typevar().and_then(|bound_typevar| {
bound_typevar.typevar(context.db()).definition(context.db())
}) {
let module = parsed_module(context.db(), typevar_definition.file(context.db()))
.load(context.db());
let typevar_range = typevar_definition.full_range(context.db(), &module);

View File

@ -1587,7 +1587,6 @@ impl<'db> SpecializationBuilder<'db> {
upper: Vec<Type<'db>>,
}
let constraints = constraints.limit_to_valid_specializations(self.db);
let mut sorted_paths = Vec::new();
constraints.for_each_path(self.db, |path| {
let mut path: Vec<_> = path.positive_constraints().collect();
@ -1884,8 +1883,15 @@ impl<'db> SpecializationBuilder<'db> {
return Ok(());
}
let when =
actual.when_constraint_set_assignable_to(self.db, formal, self.inferable);
let when = actual
.when_constraint_set_assignable_to(self.db, formal, self.inferable)
.limit_to_valid_specializations(self.db);
if when.is_never_satisfied(self.db) {
return Err(SpecializationError::NoSolution {
parameter: formal,
argument: actual,
});
}
self.add_type_mappings_from_constraint_set(formal, when, &mut f);
}
@ -1905,7 +1911,8 @@ impl<'db> SpecializationBuilder<'db> {
self.db,
formal_callable,
self.inferable,
);
)
.limit_to_valid_specializations(self.db);
self.add_type_mappings_from_constraint_set(formal, when, &mut f);
} else {
for actual_signature in &actual_callable.signatures(self.db).overloads {
@ -1914,7 +1921,8 @@ impl<'db> SpecializationBuilder<'db> {
self.db,
formal_callable,
self.inferable,
);
)
.limit_to_valid_specializations(self.db);
self.add_type_mappings_from_constraint_set(formal, when, &mut f);
}
}
@ -1931,6 +1939,10 @@ impl<'db> SpecializationBuilder<'db> {
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum SpecializationError<'db> {
NoSolution {
parameter: Type<'db>,
argument: Type<'db>,
},
MismatchedBound {
bound_typevar: BoundTypeVarInstance<'db>,
argument: Type<'db>,
@ -1942,15 +1954,17 @@ pub(crate) enum SpecializationError<'db> {
}
impl<'db> SpecializationError<'db> {
pub(crate) fn bound_typevar(&self) -> BoundTypeVarInstance<'db> {
pub(crate) fn bound_typevar(&self) -> Option<BoundTypeVarInstance<'db>> {
match self {
Self::MismatchedBound { bound_typevar, .. } => *bound_typevar,
Self::MismatchedConstraint { bound_typevar, .. } => *bound_typevar,
Self::NoSolution { .. } => None,
Self::MismatchedBound { bound_typevar, .. } => Some(*bound_typevar),
Self::MismatchedConstraint { bound_typevar, .. } => Some(*bound_typevar),
}
}
pub(crate) fn argument_type(&self) -> Type<'db> {
match self {
Self::NoSolution { argument, .. } => *argument,
Self::MismatchedBound { argument, .. } => *argument,
Self::MismatchedConstraint { argument, .. } => *argument,
}