mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Allow derived->base conversions with compatible qualifiers (#7415)
Move the existing derived->base conversion earlier in `PerformBuiltinConversion`, into the block that handles qualifier conversions. This allows, for example, converting from `partial Derived` to `partial Base` -- see the tests in `toolchain/check/testdata/class/inheritance/derived_to_base.carbon`.
This commit is contained in:
+13
-11
@@ -1322,7 +1322,12 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id,
|
||||
target.is_explicit_as()
|
||||
? context.types().GetTransitiveUnqualifiedAdaptedType(value_type_id)
|
||||
: context.types().GetUnqualifiedTypeAndQualifiers(value_type_id);
|
||||
if (target_foundation_id == value_foundation_id) {
|
||||
auto inheritance_path = ComputeInheritancePath(
|
||||
context, loc_id, value_foundation_id, target_foundation_id);
|
||||
if (inheritance_path && inheritance_path->empty()) {
|
||||
inheritance_path = std::nullopt;
|
||||
}
|
||||
if (target_foundation_id == value_foundation_id || inheritance_path) {
|
||||
auto category = SemIR::GetExprCategory(context.sem_ir(), value_id);
|
||||
auto added_quals = target_quals & ~value_quals;
|
||||
auto removed_quals = value_quals & ~target_quals;
|
||||
@@ -1378,6 +1383,13 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id,
|
||||
context, loc_id,
|
||||
{.type_id = target.type_id, .value_id = value_id});
|
||||
}
|
||||
|
||||
// An expression of type T converts to U if T is a class derived from U.
|
||||
if (inheritance_path) {
|
||||
value_id = ConvertDerivedToBase(context, loc_id, value_id,
|
||||
*inheritance_path);
|
||||
}
|
||||
|
||||
return value_id;
|
||||
} else {
|
||||
// TODO: Produce a custom diagnostic explaining that we can't perform
|
||||
@@ -1448,16 +1460,6 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id,
|
||||
target_quals.HasAnyOf(SemIR::TypeQualifiers::Partial));
|
||||
}
|
||||
}
|
||||
|
||||
// An expression of type T converts to U if T is a class derived from U.
|
||||
//
|
||||
// TODO: Combine this with the qualifiers and adapter conversion logic above
|
||||
// to allow qualifiers and inheritance conversions to be performed together.
|
||||
if (auto path = ComputeInheritancePath(context, loc_id, value_type_id,
|
||||
target.type_id);
|
||||
path && !path->empty()) {
|
||||
return ConvertDerivedToBase(context, loc_id, value_id, *path);
|
||||
}
|
||||
}
|
||||
|
||||
// A pointer T* converts to [qualified] U* if T is the same as U, or is a
|
||||
|
||||
Reference in New Issue
Block a user