mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 19:20:13 +01:00
Gracefully handle a concrete ImplWitnessAccess in the type structure (#7214)
While this can only happen when some other error is taking place, we should handle it gracefully and report a concrete (but unmatchable) value in the type structure instead of CHECK-failing.
This commit is contained in:
@@ -53,3 +53,31 @@ fn H(U:! type, V:! Z where .Z1 impls (Y where .Y1 = U)) {
|
||||
// query's.
|
||||
V as X(U);
|
||||
}
|
||||
|
||||
// --- fail_concrete_impl_witness_access_in_type_structure.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z(T:! type) {
|
||||
let Z1:! type;
|
||||
}
|
||||
interface Y {}
|
||||
|
||||
class C;
|
||||
|
||||
// Converting to this facet type requires a lookup for `C.(Z(C).Z1) as Y`. That
|
||||
// has a type structure that contains a fully concrete ImplWitnessAccess. But if
|
||||
// the lookup fails because there is no impl for `C as Z(C)`, then the access
|
||||
// remains in the type structure as is. This test ensures the type structure can
|
||||
// handle this edge case.
|
||||
fn F(unused T:! Z(.Self) where C impls (Z(C) where .Z1 impls Y)) {}
|
||||
|
||||
fn G(T:! Z(.Self)) {
|
||||
// CHECK:STDERR: fail_concrete_impl_witness_access_in_type_structure.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `Z(.Self)` into type implementing `Z(.Self) where C impls Z(C) and C.(Z(C).Z1) impls Y` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_concrete_impl_witness_access_in_type_structure.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
|
||||
// CHECK:STDERR: fn F(unused T:! Z(.Self) where C impls (Z(C) where .Z1 impls Y)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T);
|
||||
}
|
||||
|
||||
@@ -254,10 +254,8 @@ auto TypeIterator::ProcessType(InstId inst_id) -> std::optional<Step> {
|
||||
// We return FacetValues as a separate iterative step, then also recurse
|
||||
// into the the self value being accessed.
|
||||
//
|
||||
// Witness access of a concrete value would have evaluated to the accessed
|
||||
// value, so we only see ImplWitnessAccess in a type when it's a symbolic
|
||||
// value, which implies it contains a LookupImplWitness.
|
||||
CARBON_CHECK(sem_ir_->constant_values().Get(inst_id).is_symbolic());
|
||||
// If ImplWitnessAccess did not evaluate to some other value, it must
|
||||
// contain a non-final witness.
|
||||
auto witness =
|
||||
sem_ir_->insts().GetAs<LookupImplWitness>(access.witness_id);
|
||||
// Recurse into symbolic ImplWitnessAccess, replacing it with the self
|
||||
|
||||
Reference in New Issue
Block a user