mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Allow impl redecl in match_first after a definition (#7491)
Previously the last decl had to be the definition. Now we allow a declaration after a definition, so that the user can write a match_first block last, and put (re-)declarations of impls in it, after the definitions have already been written elsewhere. We track the location of the decl that was associated with a match_first block so that we can correctly point to it in diagnostics when an impl is written twice in match_first blocks. Since impls may not be redeclared across an import boundary, we will never have a `SemIR::Impl` with a match_first from a different file in a redeclaration, so we don't need to import the location of a previous decl that was in a match_first for diagnostics. As such we just store a LocId on the `SemIR::Impl` struct.
This commit is contained in:
+42
-25
@@ -76,8 +76,8 @@ interface Z {}
|
||||
final impl () as Z;
|
||||
match_first {
|
||||
// This is not seen as a redecl of the `final impl`. It's not valid to write
|
||||
// this `impl` since it overlaps the `final impl`, but we already have a
|
||||
// diagnostic.
|
||||
// an `impl` in `match_first` that overlaps a `final impl`, but we already
|
||||
// have a diagnostic.
|
||||
impl () as Z {}
|
||||
}
|
||||
|
||||
@@ -89,8 +89,8 @@ interface Z {}
|
||||
final impl () as Z {}
|
||||
match_first {
|
||||
// This is not seen as a redecl of the `final impl`. It's not valid to write
|
||||
// this `impl` since it overlaps the `final impl`, but we already have a
|
||||
// diagnostic.
|
||||
// an `impl` in `match_first` that overlaps a `final impl`, but we already
|
||||
// have a diagnostic.
|
||||
// CHECK:STDERR: fail_final_redecl_defined_once.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]
|
||||
// CHECK:STDERR: impl () as Z;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
@@ -106,8 +106,8 @@ interface Z {}
|
||||
final impl () as Z {}
|
||||
match_first {
|
||||
// This is not seen as a redecl of the `final impl`. It's not valid to write
|
||||
// this `impl` since it overlaps the `final impl`, but we already have a
|
||||
// diagnostic.
|
||||
// an `impl` in `match_first` that overlaps a `final impl`, but we already
|
||||
// have a diagnostic.
|
||||
// CHECK:STDERR: fail_final_redecl_defined_twice.carbon:[[@LINE+7]]:3: error: `impl` will never be used [ImplFinalOverlapsNonFinal]
|
||||
// CHECK:STDERR: impl () as Z {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~
|
||||
@@ -125,9 +125,9 @@ interface Z {}
|
||||
|
||||
final impl () as Z;
|
||||
match_first {
|
||||
// This is not seen as a redecl of the `final impl`. It's not valid to write
|
||||
// this `impl` since it overlaps the `final impl`, but we already have a
|
||||
// diagnostic.
|
||||
// This _is_ seen as a redecl of the `final impl`. It's not valid to write
|
||||
// an `impl` in `match_first` that overlaps a `final impl`, but we already
|
||||
// have a diagnostic.
|
||||
// CHECK:STDERR: fail_final_final_redecl.carbon:[[@LINE+7]]:3: error: `final impl` in `match_first` block [FinalImplInMatchFirst]
|
||||
// CHECK:STDERR: final impl () as Z {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
|
||||
@@ -184,21 +184,13 @@ match_first {
|
||||
}
|
||||
impl () as Z {}
|
||||
|
||||
// --- fail_todo_redecl_after_defined.carbon
|
||||
// --- redecl_after_defined.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {}
|
||||
|
||||
impl () as Z {}
|
||||
match_first {
|
||||
// TODO: We want to allow a redecl in match_first after the definition.
|
||||
// CHECK:STDERR: fail_todo_redecl_after_defined.carbon:[[@LINE+7]]:3: error: redefinition of `impl () as Z` [ImplRedefinition]
|
||||
// CHECK:STDERR: impl () as Z;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_redecl_after_defined.carbon:[[@LINE-6]]:1: note: previous definition was here [ImplPreviousDefinition]
|
||||
// CHECK:STDERR: impl () as Z {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl () as Z;
|
||||
}
|
||||
|
||||
@@ -334,16 +326,35 @@ interface Z {}
|
||||
|
||||
match_first {
|
||||
impl () as Z {}
|
||||
// CHECK:STDERR: fail_redecl_after_defined_in_same_block.carbon:[[@LINE+7]]:3: error: redefinition of `impl () as Z` [ImplRedefinition]
|
||||
// CHECK:STDERR: fail_redecl_after_defined_in_same_block.carbon:[[@LINE+7]]:3: error: impl declared in `match_first` more than once [ImplInTwoMatchFirst]
|
||||
// CHECK:STDERR: impl () as Z;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_redecl_after_defined_in_same_block.carbon:[[@LINE-4]]:3: note: previous definition was here [ImplPreviousDefinition]
|
||||
// CHECK:STDERR: fail_redecl_after_defined_in_same_block.carbon:[[@LINE-4]]:3: note: previous declaration here [ImplInTwoMatchFirstNote]
|
||||
// CHECK:STDERR: impl () as Z {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl () as Z;
|
||||
}
|
||||
|
||||
// --- fail_two_redecl_in_same_block.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {}
|
||||
|
||||
impl () as Z {}
|
||||
match_first {
|
||||
impl () as Z;
|
||||
// TODO: This "previous declaration" location is wrong. The redecl came after.
|
||||
// CHECK:STDERR: fail_two_redecl_in_same_block.carbon:[[@LINE+7]]:3: error: impl declared in `match_first` more than once [ImplInTwoMatchFirst]
|
||||
// CHECK:STDERR: impl () as Z;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_two_redecl_in_same_block.carbon:[[@LINE-5]]:3: note: previous declaration here [ImplInTwoMatchFirstNote]
|
||||
// CHECK:STDERR: impl () as Z;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl () as Z;
|
||||
}
|
||||
|
||||
// --- fail_redecl_in_different_block.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -373,10 +384,10 @@ match_first {
|
||||
impl () as Z {}
|
||||
}
|
||||
match_first {
|
||||
// CHECK:STDERR: fail_redecl_defined_in_different_block_firset.carbon:[[@LINE+7]]:3: error: redefinition of `impl () as Z` [ImplRedefinition]
|
||||
// CHECK:STDERR: fail_redecl_defined_in_different_block_firset.carbon:[[@LINE+7]]:3: error: impl declared in `match_first` more than once [ImplInTwoMatchFirst]
|
||||
// CHECK:STDERR: impl () as Z;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_redecl_defined_in_different_block_firset.carbon:[[@LINE-6]]:3: note: previous definition was here [ImplPreviousDefinition]
|
||||
// CHECK:STDERR: fail_redecl_defined_in_different_block_firset.carbon:[[@LINE-6]]:3: note: previous declaration here [ImplInTwoMatchFirstNote]
|
||||
// CHECK:STDERR: impl () as Z {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
@@ -460,6 +471,7 @@ final match_first {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: extend %Z.ref.loc6
|
||||
// CHECK:STDOUT: match_first = position 0
|
||||
// CHECK:STDOUT: witness = %Z.impl_witness
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -486,6 +498,7 @@ final match_first {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: extend %Z.ref
|
||||
// CHECK:STDOUT: match_first = position 0
|
||||
// CHECK:STDOUT: witness = %Z.impl_witness
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -510,6 +523,7 @@ final match_first {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: extend %Z.ref.loc5
|
||||
// CHECK:STDOUT: match_first = position 0
|
||||
// CHECK:STDOUT: witness = %Z.impl_witness
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -529,11 +543,12 @@ final match_first {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: final impl @empty_tuple.type.as.Z.impl: %.loc5_7.2 as %Z.ref.loc5 {
|
||||
// CHECK:STDOUT: impl @empty_tuple.type.as.Z.impl: %.loc5_7.2 as %Z.ref.loc5 {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: extend %Z.ref.loc5
|
||||
// CHECK:STDOUT: match_first = position 0, final
|
||||
// CHECK:STDOUT: witness = %Z.impl_witness
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -553,11 +568,12 @@ final match_first {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: final impl @empty_tuple.type.as.Z.impl: %.loc6_9.2 as %Z.ref.loc6 {
|
||||
// CHECK:STDOUT: impl @empty_tuple.type.as.Z.impl: %.loc6_9.2 as %Z.ref.loc6 {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: extend %Z.ref.loc6
|
||||
// CHECK:STDOUT: match_first = position 0, final
|
||||
// CHECK:STDOUT: witness = %Z.impl_witness
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -577,11 +593,12 @@ final match_first {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: final impl @empty_tuple.type.as.Z.impl: %.loc5_7.2 as %Z.ref.loc5 {
|
||||
// CHECK:STDOUT: impl @empty_tuple.type.as.Z.impl: %.loc5_7.2 as %Z.ref.loc5 {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: extend %Z.ref.loc5
|
||||
// CHECK:STDOUT: match_first = position 0, final
|
||||
// CHECK:STDOUT: witness = %Z.impl_witness
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
Reference in New Issue
Block a user