forked from carbon-language/carbon-lang
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support implicit conversion from a type value to a facet value (carbo…
…n-language#4863) If a type satisfies the requirements of a FacetType, then that type as a value can be converted to a FacetValue, which binds the type value to the FacetType. For instance, if the class A implements an interface B, then ``` fn F(b:! B) {} ``` can be called with the type `A` ``` F(A); ``` This does not handle yet receiving non-type values matching a FacetType, as that requires deducing the required FacetValue for the caller's argument. Follow-up work will do this step. --------- Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
- Loading branch information
Showing
5 changed files
with
346 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
...ain/check/testdata/builtin_conversions/no_prelude/convert_class_type_to_facet_type.carbon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// 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 | ||
// TIP: To test this file alone, run: | ||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtin_conversions/no_prelude/convert_class_type_to_facet_type.carbon | ||
// TIP: To dump output, run: | ||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtin_conversions/no_prelude/convert_class_type_to_facet_type.carbon | ||
|
||
interface Animal {} | ||
|
||
class Goat {} | ||
impl Goat as Animal {} | ||
|
||
fn WalkAnimal(A:! Animal) {} | ||
|
||
fn F() { | ||
WalkAnimal(Goat); | ||
} | ||
|
||
// CHECK:STDOUT: --- convert_class_type_to_facet_type.carbon | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: constants { | ||
// CHECK:STDOUT: %Animal.type: type = facet_type <@Animal> [template] | ||
// CHECK:STDOUT: %Self: %Animal.type = bind_symbolic_name Self, 0 [symbolic] | ||
// CHECK:STDOUT: %Goat: type = class_type @Goat [template] | ||
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [template] | ||
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [template] | ||
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template] | ||
// CHECK:STDOUT: %impl_witness: <witness> = impl_witness () [template] | ||
// CHECK:STDOUT: %A: %Animal.type = bind_symbolic_name A, 0 [symbolic] | ||
// CHECK:STDOUT: %A.patt: %Animal.type = symbolic_binding_pattern A, 0 [symbolic] | ||
// CHECK:STDOUT: %WalkAnimal.type: type = fn_type @WalkAnimal [template] | ||
// CHECK:STDOUT: %WalkAnimal: %WalkAnimal.type = struct_value () [template] | ||
// CHECK:STDOUT: %F.type: type = fn_type @F [template] | ||
// CHECK:STDOUT: %F: %F.type = struct_value () [template] | ||
// CHECK:STDOUT: %Animal.facet: %Animal.type = facet_value %Goat, %impl_witness [template] | ||
// CHECK:STDOUT: %WalkAnimal.specific_fn: <specific function> = specific_function %WalkAnimal, @WalkAnimal(%Animal.facet) [template] | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: file { | ||
// CHECK:STDOUT: package: <namespace> = namespace [template] { | ||
// CHECK:STDOUT: .Animal = %Animal.decl | ||
// CHECK:STDOUT: .Goat = %Goat.decl | ||
// CHECK:STDOUT: .WalkAnimal = %WalkAnimal.decl | ||
// CHECK:STDOUT: .F = %F.decl | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: %Animal.decl: type = interface_decl @Animal [template = constants.%Animal.type] {} {} | ||
// CHECK:STDOUT: %Goat.decl: type = class_decl @Goat [template = constants.%Goat] {} {} | ||
// CHECK:STDOUT: impl_decl @impl [template] {} { | ||
// CHECK:STDOUT: %Goat.ref: type = name_ref Goat, file.%Goat.decl [template = constants.%Goat] | ||
// CHECK:STDOUT: %Animal.ref: type = name_ref Animal, file.%Animal.decl [template = constants.%Animal.type] | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: %impl_witness: <witness> = impl_witness () [template = constants.%impl_witness] | ||
// CHECK:STDOUT: %WalkAnimal.decl: %WalkAnimal.type = fn_decl @WalkAnimal [template = constants.%WalkAnimal] { | ||
// CHECK:STDOUT: %A.patt.loc16_15.1: %Animal.type = symbolic_binding_pattern A, 0 [symbolic = %A.patt.loc16_15.2 (constants.%A.patt)] | ||
// CHECK:STDOUT: %A.param_patt: %Animal.type = value_param_pattern %A.patt.loc16_15.1, runtime_param<none> [symbolic = %A.patt.loc16_15.2 (constants.%A.patt)] | ||
// CHECK:STDOUT: } { | ||
// CHECK:STDOUT: %A.param: %Animal.type = value_param runtime_param<none> | ||
// CHECK:STDOUT: %Animal.ref: type = name_ref Animal, file.%Animal.decl [template = constants.%Animal.type] | ||
// CHECK:STDOUT: %A.loc16_15.1: %Animal.type = bind_symbolic_name A, 0, %A.param [symbolic = %A.loc16_15.2 (constants.%A)] | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} {} | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: interface @Animal { | ||
// CHECK:STDOUT: %Self: %Animal.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: !members: | ||
// CHECK:STDOUT: .Self = %Self | ||
// CHECK:STDOUT: witness = () | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: impl @impl: %Goat.ref as %Animal.ref { | ||
// CHECK:STDOUT: !members: | ||
// CHECK:STDOUT: witness = file.%impl_witness | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: class @Goat { | ||
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [template = constants.%complete_type] | ||
// CHECK:STDOUT: complete_type_witness = %complete_type | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: !members: | ||
// CHECK:STDOUT: .Self = constants.%Goat | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: generic fn @WalkAnimal(%A.loc16_15.1: %Animal.type) { | ||
// CHECK:STDOUT: %A.loc16_15.2: %Animal.type = bind_symbolic_name A, 0 [symbolic = %A.loc16_15.2 (constants.%A)] | ||
// CHECK:STDOUT: %A.patt.loc16_15.2: %Animal.type = symbolic_binding_pattern A, 0 [symbolic = %A.patt.loc16_15.2 (constants.%A.patt)] | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: !definition: | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: fn(%A.param_patt: %Animal.type) { | ||
// CHECK:STDOUT: !entry: | ||
// CHECK:STDOUT: return | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: fn @F() { | ||
// CHECK:STDOUT: !entry: | ||
// CHECK:STDOUT: %WalkAnimal.ref: %WalkAnimal.type = name_ref WalkAnimal, file.%WalkAnimal.decl [template = constants.%WalkAnimal] | ||
// CHECK:STDOUT: %Goat.ref: type = name_ref Goat, file.%Goat.decl [template = constants.%Goat] | ||
// CHECK:STDOUT: %Animal.facet: %Animal.type = facet_value %Goat.ref, constants.%impl_witness [template = constants.%Animal.facet] | ||
// CHECK:STDOUT: %.loc19: %Animal.type = converted %Goat.ref, %Animal.facet [template = constants.%Animal.facet] | ||
// CHECK:STDOUT: %WalkAnimal.specific_fn: <specific function> = specific_function %WalkAnimal.ref, @WalkAnimal(constants.%Animal.facet) [template = constants.%WalkAnimal.specific_fn] | ||
// CHECK:STDOUT: %WalkAnimal.call: init %empty_tuple.type = call %WalkAnimal.specific_fn() | ||
// CHECK:STDOUT: return | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: specific @WalkAnimal(constants.%A) { | ||
// CHECK:STDOUT: %A.loc16_15.2 => constants.%A | ||
// CHECK:STDOUT: %A.patt.loc16_15.2 => constants.%A | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: specific @WalkAnimal(constants.%Animal.facet) { | ||
// CHECK:STDOUT: %A.loc16_15.2 => constants.%Animal.facet | ||
// CHECK:STDOUT: %A.patt.loc16_15.2 => constants.%Animal.facet | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: !definition: | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: |
152 changes: 152 additions & 0 deletions
152
...stdata/builtin_conversions/no_prelude/fail_todo_convert_facet_value_to_facet_value.carbon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
// 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 | ||
// TIP: To test this file alone, run: | ||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtin_conversions/no_prelude/fail_todo_convert_facet_value_to_facet_value.carbon | ||
// TIP: To dump output, run: | ||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtin_conversions/no_prelude/fail_todo_convert_facet_value_to_facet_value.carbon | ||
|
||
interface Eats {} | ||
interface Goat {} | ||
|
||
class Ginger {} | ||
impl Ginger as Goat {} | ||
|
||
impl Goat as Eats {} | ||
|
||
fn Feed(e:! Eats) {} | ||
|
||
fn F() { | ||
// CHECK:STDERR: fail_todo_convert_facet_value_to_facet_value.carbon:[[@LINE+14]]:3: error: semantics TODO: `Facet value converting to facet value` [SemanticsTodo] | ||
// CHECK:STDERR: Feed(Ginger as Goat); | ||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ | ||
// CHECK:STDERR: fail_todo_convert_facet_value_to_facet_value.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere] | ||
// CHECK:STDERR: fn Feed(e:! Eats) {} | ||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ | ||
// CHECK:STDERR: | ||
// CHECK:STDERR: fail_todo_convert_facet_value_to_facet_value.carbon:[[@LINE+7]]:3: error: `Core.ImplicitAs` implicitly referenced here, but package `Core` not found [CoreNotFound] | ||
// CHECK:STDERR: Feed(Ginger as Goat); | ||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ | ||
// CHECK:STDERR: fail_todo_convert_facet_value_to_facet_value.carbon:[[@LINE-13]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere] | ||
// CHECK:STDERR: fn Feed(e:! Eats) {} | ||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ | ||
// CHECK:STDERR: | ||
Feed(Ginger as Goat); | ||
} | ||
|
||
// CHECK:STDOUT: --- fail_todo_convert_facet_value_to_facet_value.carbon | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: constants { | ||
// CHECK:STDOUT: %Eats.type: type = facet_type <@Eats> [template] | ||
// CHECK:STDOUT: %Self.1b5: %Eats.type = bind_symbolic_name Self, 0 [symbolic] | ||
// CHECK:STDOUT: %Goat.type: type = facet_type <@Goat> [template] | ||
// CHECK:STDOUT: %Self.092: %Goat.type = bind_symbolic_name Self, 0 [symbolic] | ||
// CHECK:STDOUT: %Ginger: type = class_type @Ginger [template] | ||
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [template] | ||
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [template] | ||
// CHECK:STDOUT: %impl_witness: <witness> = impl_witness () [template] | ||
// CHECK:STDOUT: %e: %Eats.type = bind_symbolic_name e, 0 [symbolic] | ||
// CHECK:STDOUT: %e.patt: %Eats.type = symbolic_binding_pattern e, 0 [symbolic] | ||
// CHECK:STDOUT: %Feed.type: type = fn_type @Feed [template] | ||
// CHECK:STDOUT: %Feed: %Feed.type = struct_value () [template] | ||
// CHECK:STDOUT: %F.type: type = fn_type @F [template] | ||
// CHECK:STDOUT: %F: %F.type = struct_value () [template] | ||
// CHECK:STDOUT: %Goat.facet: %Goat.type = facet_value %Ginger, %impl_witness [template] | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: file { | ||
// CHECK:STDOUT: package: <namespace> = namespace [template] { | ||
// CHECK:STDOUT: .Eats = %Eats.decl | ||
// CHECK:STDOUT: .Goat = %Goat.decl | ||
// CHECK:STDOUT: .Ginger = %Ginger.decl | ||
// CHECK:STDOUT: .Feed = %Feed.decl | ||
// CHECK:STDOUT: .F = %F.decl | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: %Eats.decl: type = interface_decl @Eats [template = constants.%Eats.type] {} {} | ||
// CHECK:STDOUT: %Goat.decl: type = interface_decl @Goat [template = constants.%Goat.type] {} {} | ||
// CHECK:STDOUT: %Ginger.decl: type = class_decl @Ginger [template = constants.%Ginger] {} {} | ||
// CHECK:STDOUT: impl_decl @impl.1 [template] {} { | ||
// CHECK:STDOUT: %Ginger.ref: type = name_ref Ginger, file.%Ginger.decl [template = constants.%Ginger] | ||
// CHECK:STDOUT: %Goat.ref: type = name_ref Goat, file.%Goat.decl [template = constants.%Goat.type] | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: %impl_witness.loc15: <witness> = impl_witness () [template = constants.%impl_witness] | ||
// CHECK:STDOUT: impl_decl @impl.2 [template] {} { | ||
// CHECK:STDOUT: %Goat.ref: type = name_ref Goat, file.%Goat.decl [template = constants.%Goat.type] | ||
// CHECK:STDOUT: %Eats.ref: type = name_ref Eats, file.%Eats.decl [template = constants.%Eats.type] | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: %impl_witness.loc17: <witness> = impl_witness () [template = constants.%impl_witness] | ||
// CHECK:STDOUT: %Feed.decl: %Feed.type = fn_decl @Feed [template = constants.%Feed] { | ||
// CHECK:STDOUT: %e.patt.loc19_9.1: %Eats.type = symbolic_binding_pattern e, 0 [symbolic = %e.patt.loc19_9.2 (constants.%e.patt)] | ||
// CHECK:STDOUT: %e.param_patt: %Eats.type = value_param_pattern %e.patt.loc19_9.1, runtime_param<none> [symbolic = %e.patt.loc19_9.2 (constants.%e.patt)] | ||
// CHECK:STDOUT: } { | ||
// CHECK:STDOUT: %e.param: %Eats.type = value_param runtime_param<none> | ||
// CHECK:STDOUT: %Eats.ref: type = name_ref Eats, file.%Eats.decl [template = constants.%Eats.type] | ||
// CHECK:STDOUT: %e.loc19_9.1: %Eats.type = bind_symbolic_name e, 0, %e.param [symbolic = %e.loc19_9.2 (constants.%e)] | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} {} | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: interface @Eats { | ||
// CHECK:STDOUT: %Self: %Eats.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.1b5] | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: !members: | ||
// CHECK:STDOUT: .Self = %Self | ||
// CHECK:STDOUT: witness = () | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: interface @Goat { | ||
// CHECK:STDOUT: %Self: %Goat.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.092] | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: !members: | ||
// CHECK:STDOUT: .Self = %Self | ||
// CHECK:STDOUT: witness = () | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: impl @impl.1: %Ginger.ref as %Goat.ref { | ||
// CHECK:STDOUT: !members: | ||
// CHECK:STDOUT: witness = file.%impl_witness.loc15 | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: impl @impl.2: %Goat.ref as %Eats.ref { | ||
// CHECK:STDOUT: !members: | ||
// CHECK:STDOUT: witness = file.%impl_witness.loc17 | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: class @Ginger { | ||
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [template = constants.%complete_type] | ||
// CHECK:STDOUT: complete_type_witness = %complete_type | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: !members: | ||
// CHECK:STDOUT: .Self = constants.%Ginger | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: generic fn @Feed(%e.loc19_9.1: %Eats.type) { | ||
// CHECK:STDOUT: %e.loc19_9.2: %Eats.type = bind_symbolic_name e, 0 [symbolic = %e.loc19_9.2 (constants.%e)] | ||
// CHECK:STDOUT: %e.patt.loc19_9.2: %Eats.type = symbolic_binding_pattern e, 0 [symbolic = %e.patt.loc19_9.2 (constants.%e.patt)] | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: !definition: | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: fn(%e.param_patt: %Eats.type) { | ||
// CHECK:STDOUT: !entry: | ||
// CHECK:STDOUT: return | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: fn @F() { | ||
// CHECK:STDOUT: !entry: | ||
// CHECK:STDOUT: %Feed.ref: %Feed.type = name_ref Feed, file.%Feed.decl [template = constants.%Feed] | ||
// CHECK:STDOUT: %Ginger.ref: type = name_ref Ginger, file.%Ginger.decl [template = constants.%Ginger] | ||
// CHECK:STDOUT: %Goat.ref: type = name_ref Goat, file.%Goat.decl [template = constants.%Goat.type] | ||
// CHECK:STDOUT: %Goat.facet: %Goat.type = facet_value %Ginger.ref, constants.%impl_witness [template = constants.%Goat.facet] | ||
// CHECK:STDOUT: %.loc36_15: %Goat.type = converted %Ginger.ref, %Goat.facet [template = constants.%Goat.facet] | ||
// CHECK:STDOUT: %.loc36_22: %Eats.type = converted %.loc36_15, <error> [template = <error>] | ||
// CHECK:STDOUT: return | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: | ||
// CHECK:STDOUT: specific @Feed(constants.%e) { | ||
// CHECK:STDOUT: %e.loc19_9.2 => constants.%e | ||
// CHECK:STDOUT: %e.patt.loc19_9.2 => constants.%e | ||
// CHECK:STDOUT: } | ||
// CHECK:STDOUT: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.