mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-03 22:02:51 +01:00
This is only fixing the decision about *whether* to produce a witness. Implementation of the witness is still a TODO, though where a body is generated, it should also precisely reflect where one _needs_ to be generated. Note the tests: - toolchain/lower/testdata/function/generic/import_core_witness.carbon - toolchain/lower/testdata/function/generic/import_unused_def.carbon These tests can probably be produced _without_ Core.Destroy, but I found the essence of them while trying to build //examples with Core.Destroy and a simpler minimization wasn't striking me. Assisted-by: Google Antigravity with Gemini --------- Co-authored-by: jonmeow <jperkins@google.com>
129 lines
3.4 KiB
Plaintext
129 lines
3.4 KiB
Plaintext
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
|
|
//
|
|
// AUTOUPDATE
|
|
// TIP: To test this file alone, run:
|
|
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/lookup/find_in_final.carbon
|
|
// TIP: To dump output, run:
|
|
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/lookup/find_in_final.carbon
|
|
|
|
// --- final_impl_precedence_over_facet.carbon
|
|
library "[[@TEST_NAME]]";
|
|
interface I {
|
|
let T:! type;
|
|
}
|
|
|
|
final impl forall [U:! type] U as I where .T = () {}
|
|
|
|
fn F(V:! I) -> V.T {
|
|
// Even though we have a witness that `V impls I` from the constraint on `I`,
|
|
// we should do an impl lookup to see if any effectively final impl applies
|
|
// when we find an unknown value in that witness. In this case, that lookup
|
|
// would find an impl with more specific values for associated constants that
|
|
// we should merge.
|
|
return ();
|
|
}
|
|
|
|
// --- final_impl_precedence_over_facet_with_where.carbon
|
|
library "[[@TEST_NAME]]";
|
|
|
|
interface Z {
|
|
let X:! type;
|
|
let Y:! type;
|
|
}
|
|
|
|
final impl forall [T:! type] T as Z where .X = () and .Y = () {}
|
|
|
|
fn F(ZZ:! Z where .X = ()) {
|
|
// Z.Y is unspecified on `ZZ` so it's found on the final impl where it's known
|
|
// to be the concrete type (), which can then be used in this generic
|
|
// function.
|
|
let unused a: ZZ.Y = ();
|
|
}
|
|
|
|
// --- final_impl_precedence_over_facet_access_type_with_where.carbon
|
|
library "[[@TEST_NAME]]";
|
|
|
|
interface Z {
|
|
let X:! type;
|
|
let Y:! type;
|
|
}
|
|
|
|
final impl forall [T:! type] T as Z where .X = () and .Y = () {}
|
|
|
|
fn F[T:! Z where .X = ()](z: T) {
|
|
// z.Y is unspecified on `ZZ` so it's found on the final impl where it's known
|
|
// to be the concrete type (), which can then be used in this generic
|
|
// function.
|
|
let unused a: z.Y = ();
|
|
}
|
|
|
|
// --- final_impl_makes_compatible_facet_values.carbon
|
|
library "[[@TEST_NAME]]";
|
|
|
|
interface I { let X:! type; }
|
|
interface J {}
|
|
|
|
final impl forall [T:! J] T as I where .X = () {}
|
|
|
|
class C(T:! I) {
|
|
var b: T.X;
|
|
}
|
|
|
|
class D(T:! J) {
|
|
var c: C(T)*;
|
|
}
|
|
|
|
fn F(T:! I & J) -> () {
|
|
// The witness for `I` found here directly, and inside `D` from a FacetValue
|
|
// come from the same facet, the `T` binding in the params of F, so they
|
|
// should be compatible.
|
|
var x: C(T);
|
|
var y: D(T);
|
|
y.c = &x;
|
|
return (*y.c).b;
|
|
}
|
|
|
|
// --- non_final_impl_makes_compatible_facet_values.carbon
|
|
library "[[@TEST_NAME]]";
|
|
|
|
interface I { let X:! Core.Destroy; }
|
|
interface J {}
|
|
|
|
impl forall [T:! J] T as I where .X = () {}
|
|
|
|
class C(T:! I) {
|
|
var b: T.X;
|
|
}
|
|
|
|
class D(T:! J) {
|
|
var c: C(T)*;
|
|
}
|
|
|
|
fn F(T:! I & J) -> T.(I.X)* {
|
|
var x: C(T);
|
|
var y: D(T);
|
|
// The witness for `I` found here directly, and inside `D` from a FacetValue
|
|
// come from the same facet, the `T` binding in the params of F, so they
|
|
// should be compatible.
|
|
y.c = &x;
|
|
return &(*y.c).b;
|
|
}
|
|
|
|
// --- todo_fail_facet_value_rewrite_incompatible_with_final_impl.carbon
|
|
library "[[@TEST_NAME]]";
|
|
|
|
interface Z {
|
|
let X:! type;
|
|
}
|
|
|
|
final impl forall [T:! type] T as Z where .X = () {}
|
|
|
|
// TODO: This should be diagnosed as there is a final impl defining `.X = ()`,
|
|
// which makes the LHS of this rewrite constraint concrete. And since the RHS is
|
|
// not the same (or convertible from), the rewrite is impossible.
|
|
fn F(unused ZZ:! Z where .X = {.r: ()}) {}
|