mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-03 17:45:49 +01:00
The strategy that we use for now to support template instantiation is to check the impl declaration as if it were a generic, but to defer all checking of the impl definition until we see a use in which all template parameters have arguments. At that point, we clone the impl definition and type-check the whole thing, with constant values set on the template parameters corresponding to the given arguments. No caching of template instantiations is performed yet; each time we form a reference to a template instantiation, we instantiate it afresh. We also don't implement the name lookup rule from #949 yet; lookups during template instantiation look only in the actual type and not in the constraint. Depends on #2699
78 lines
1.9 KiB
Plaintext
78 lines
1.9 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
|
|
//
|
|
// AUTOUPDATE
|
|
// RUN: %{explorer-run}
|
|
// RUN: %{explorer-run-trace}
|
|
// CHECK:STDOUT: MemberF.F
|
|
// CHECK:STDOUT: ImplF.(HasF.F)
|
|
// CHECK:STDOUT: BothFs.(HasF.F)
|
|
// CHECK:STDOUT: BothFs.F
|
|
// CHECK:STDOUT: BothFs.F
|
|
// CHECK:STDOUT: result: 0
|
|
|
|
package ExplorerTest api;
|
|
|
|
choice ImplKind {
|
|
Checked,
|
|
ConstrainedTemplate,
|
|
UnconstrainedTemplate
|
|
}
|
|
|
|
interface CallF(K:! ImplKind) {
|
|
fn DoIt[self: Self]();
|
|
}
|
|
|
|
interface HasF {
|
|
fn F[self: Self]();
|
|
}
|
|
|
|
impl forall [T:! HasF] T as CallF(ImplKind.Checked) {
|
|
fn DoIt[self: Self]() { self.F(); }
|
|
}
|
|
|
|
impl forall [template T:! HasF] T as CallF(ImplKind.ConstrainedTemplate) {
|
|
fn DoIt[self: Self]() { self.F(); }
|
|
}
|
|
|
|
impl forall [template T:! type] T as CallF(ImplKind.UnconstrainedTemplate) {
|
|
fn DoIt[self: Self]() { self.F(); }
|
|
}
|
|
|
|
class MemberF {
|
|
fn F[self: Self]() { Print("MemberF.F"); }
|
|
}
|
|
|
|
class ImplF {}
|
|
external impl ImplF as HasF {
|
|
fn F[self: Self]() { Print("ImplF.(HasF.F)"); }
|
|
}
|
|
|
|
class BothFs {
|
|
fn F[self: Self]() { Print("BothFs.F"); }
|
|
}
|
|
external impl BothFs as HasF {
|
|
fn F[self: Self]() { Print("BothFs.(HasF.F)"); }
|
|
}
|
|
|
|
fn Main() -> i32 {
|
|
var mem: MemberF = {};
|
|
var imp: ImplF = {};
|
|
var both: BothFs = {};
|
|
|
|
mem.(CallF(ImplKind.UnconstrainedTemplate).DoIt)();
|
|
|
|
imp.(CallF(ImplKind.Checked).DoIt)();
|
|
// TODO: Should be valid, but currently fails during instantiation.
|
|
//imp.(CallF(ImplKind.ConstrainedTemplate).DoIt)();
|
|
|
|
both.(CallF(ImplKind.Checked).DoIt)();
|
|
// TODO: Should be rejected, but currently incorrectly accepted.
|
|
// This line can be deleted once it starts failing; we test that this is
|
|
// rejected in fail_name_lookup.carbon.
|
|
both.(CallF(ImplKind.ConstrainedTemplate).DoIt)();
|
|
both.(CallF(ImplKind.UnconstrainedTemplate).DoIt)();
|
|
return 0;
|
|
}
|