From d34f878aa9382d5938cd980b64122c13e018379d Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Sat, 18 May 2024 17:30:23 +0200 Subject: [PATCH] Add missing check for duplicated binding in the same pattern --- crates/hir-analysis/src/ty/diagnostics.rs | 89 ++++++++++++------- crates/hir-analysis/src/ty/ty_check/env.rs | 66 ++++++++++++-- crates/hir-analysis/src/ty/ty_check/pat.rs | 14 ++- .../fixtures/ty/trait_bound/coinductive.snap | 4 +- crates/uitest/fixtures/ty_check/array.snap | 4 +- crates/uitest/fixtures/ty_check/assign.snap | 10 +-- .../uitest/fixtures/ty_check/aug_assign.snap | 4 +- crates/uitest/fixtures/ty_check/binary.snap | 8 +- crates/uitest/fixtures/ty_check/call.snap | 10 +-- .../fixtures/ty_check/field_access.snap | 8 +- crates/uitest/fixtures/ty_check/for_.snap | 4 +- crates/uitest/fixtures/ty_check/index.snap | 2 +- .../fixtures/ty_check/loop_control.snap | 4 +- .../ambiguous_inherent_method.snap | 4 +- .../method_selection/ambiguous_trait_def.snap | 4 +- .../ambiguous_trait_inst.snap | 4 +- .../require_explicit_import.snap | 2 +- .../ty_check/pat/duplicated_binding.fe | 11 +++ .../ty_check/pat/duplicated_binding.snap | 22 +++++ crates/uitest/fixtures/ty_check/pat/path.snap | 2 +- .../fixtures/ty_check/pat/path_tuple.snap | 12 +-- .../uitest/fixtures/ty_check/pat/record.snap | 36 +++++--- crates/uitest/fixtures/ty_check/ret.snap | 4 +- crates/uitest/fixtures/ty_check/tuple.snap | 4 +- crates/uitest/fixtures/ty_check/unary.snap | 6 +- 25 files changed, 240 insertions(+), 98 deletions(-) create mode 100644 crates/uitest/fixtures/ty_check/pat/duplicated_binding.fe create mode 100644 crates/uitest/fixtures/ty_check/pat/duplicated_binding.snap diff --git a/crates/hir-analysis/src/ty/diagnostics.rs b/crates/hir-analysis/src/ty/diagnostics.rs index 71bd85ae2..f8c7fd39a 100644 --- a/crates/hir-analysis/src/ty/diagnostics.rs +++ b/crates/hir-analysis/src/ty/diagnostics.rs @@ -525,6 +525,11 @@ pub enum BodyDiag<'db> { TypeMismatch(DynLazySpan<'db>, String, String), InfiniteOccurrence(DynLazySpan<'db>), + DuplicatedBinding { + primary: DynLazySpan<'db>, + conflicat_with: DynLazySpan<'db>, + name: IdentId<'db>, + }, DuplicatedRestPat(DynLazySpan<'db>), InvalidPathDomainInPat { @@ -878,36 +883,37 @@ impl<'db> BodyDiag<'db> { match self { Self::TypeMismatch(..) => 0, Self::InfiniteOccurrence(..) => 1, - Self::DuplicatedRestPat(..) => 2, - Self::InvalidPathDomainInPat { .. } => 3, - Self::UnitVariantExpected { .. } => 4, - Self::TupleVariantExpected { .. } => 5, - Self::RecordExpected { .. } => 6, - Self::MismatchedFieldCount { .. } => 7, - Self::DuplicatedRecordFieldBind { .. } => 8, - Self::RecordFieldNotFound { .. } => 9, - Self::ExplicitLabelExpectedInRecord { .. } => 10, - Self::MissingRecordFields { .. } => 11, - Self::UndefinedVariable(..) => 12, - Self::ReturnedTypeMismatch { .. } => 13, - Self::TypeMustBeKnown(..) => 14, - Self::AccessedFieldNotFound { .. } => 15, - Self::OpsTraitNotImplemented { .. } => 16, - Self::NonAssignableExpr(..) => 17, - Self::ImmutableAssignment { .. } => 18, - Self::LoopControlOutsideOfLoop { .. } => 19, - Self::TraitNotImplemented { .. } => 20, - Self::NotCallable(..) => 21, - Self::CallGenericArgNumMismatch { .. } => 22, - Self::CallArgNumMismatch { .. } => 23, - Self::CallArgLabelMismatch { .. } => 24, - Self::AmbiguousInherentMethodCall { .. } => 25, - Self::AmbiguousTrait { .. } => 26, - Self::AmbiguousTraitInst { .. } => 27, - Self::InvisibleAmbiguousTrait { .. } => 28, - Self::MethodNotFound { .. } => 29, - Self::NotValue { .. } => 30, - Self::TypeAnnotationNeeded { .. } => 31, + Self::DuplicatedBinding { .. } => 2, + Self::DuplicatedRestPat(..) => 3, + Self::InvalidPathDomainInPat { .. } => 4, + Self::UnitVariantExpected { .. } => 5, + Self::TupleVariantExpected { .. } => 6, + Self::RecordExpected { .. } => 7, + Self::MismatchedFieldCount { .. } => 8, + Self::DuplicatedRecordFieldBind { .. } => 9, + Self::RecordFieldNotFound { .. } => 10, + Self::ExplicitLabelExpectedInRecord { .. } => 11, + Self::MissingRecordFields { .. } => 12, + Self::UndefinedVariable(..) => 13, + Self::ReturnedTypeMismatch { .. } => 14, + Self::TypeMustBeKnown(..) => 15, + Self::AccessedFieldNotFound { .. } => 16, + Self::OpsTraitNotImplemented { .. } => 17, + Self::NonAssignableExpr(..) => 18, + Self::ImmutableAssignment { .. } => 19, + Self::LoopControlOutsideOfLoop { .. } => 20, + Self::TraitNotImplemented { .. } => 21, + Self::NotCallable(..) => 22, + Self::CallGenericArgNumMismatch { .. } => 23, + Self::CallArgNumMismatch { .. } => 24, + Self::CallArgLabelMismatch { .. } => 25, + Self::AmbiguousInherentMethodCall { .. } => 26, + Self::AmbiguousTrait { .. } => 27, + Self::AmbiguousTraitInst { .. } => 28, + Self::InvisibleAmbiguousTrait { .. } => 29, + Self::MethodNotFound { .. } => 30, + Self::NotValue { .. } => 31, + Self::TypeAnnotationNeeded { .. } => 32, } } @@ -915,6 +921,9 @@ impl<'db> BodyDiag<'db> { match self { Self::TypeMismatch(_, _, _) => "type mismatch".to_string(), Self::InfiniteOccurrence(_) => "infinite sized type found".to_string(), + Self::DuplicatedBinding { name, .. } => { + format!("duplicated bidning `{}` in the same pattern", name.data(db)) + } Self::DuplicatedRestPat(_) => "duplicated `..` found".to_string(), Self::InvalidPathDomainInPat { .. } => "invalid item is given here".to_string(), Self::UnitVariantExpected { .. } => "expected unit variant".to_string(), @@ -990,6 +999,26 @@ impl<'db> BodyDiag<'db> { span.resolve(db), )], + Self::DuplicatedBinding { + primary, + conflicat_with, + name, + } => { + let name = name.data(db.as_hir_db()); + vec![ + SubDiagnostic::new( + LabelStyle::Primary, + format!("`{name}` is already defined in the same pattern",), + primary.resolve(db), + ), + SubDiagnostic::new( + LabelStyle::Secondary, + format!("`{name}` is defined here"), + conflicat_with.resolve(db), + ), + ] + } + Self::DuplicatedRestPat(span) => vec![SubDiagnostic::new( LabelStyle::Primary, "`..` can be used only once".to_string(), diff --git a/crates/hir-analysis/src/ty/ty_check/env.rs b/crates/hir-analysis/src/ty/ty_check/env.rs index 76b1f4fe2..e3931d5db 100644 --- a/crates/hir-analysis/src/ty/ty_check/env.rs +++ b/crates/hir-analysis/src/ty/ty_check/env.rs @@ -177,17 +177,38 @@ impl<'db> TyCheckEnv<'db> { self.pat_ty.insert(pat, ty); } - /// Register a pending binding which will be added when `flush_pending_vars` - /// is called. + /// Registers a new pending binding. + /// + /// This function adds a binding to the list of pending variables. If a + /// binding with the same name already exists, it returns the existing + /// binding. Otherwise, it returns `None`. + /// + /// To flush pending bindings to the designated scope, call + /// [`flush_pending_bindings`] in the scope. + /// + /// # Arguments + /// + /// * `name` - The identifier of the variable. + /// * `binding` - The local binding to be registered. + /// + /// # Returns + /// + /// * `Some(LocalBinding)` if a binding with the same name already exists. + /// * `None` if the binding was successfully registered. pub(super) fn register_pending_binding( &mut self, name: IdentId<'db>, binding: LocalBinding<'db>, - ) { - self.pending_vars.insert(name, binding); + ) -> Option> { + self.pending_vars.insert(name, binding) } - /// Flush pending bindings to the current scope environment. + /// Flushes all pending variable bindings into the current variable + /// environment. + /// + /// This function moves all pending bindings from the `pending_vars` map + /// into the latest `BlockEnv` in `var_env`. After this operation, the + /// `pending_vars` map will be empty. pub(super) fn flush_pending_bindings(&mut self) { let var_env = self.var_env.last_mut().unwrap(); for (name, binding) in self.pending_vars.drain() { @@ -199,6 +220,25 @@ impl<'db> TyCheckEnv<'db> { self.pending_confirmations.push((inst, span)) } + /// Completes the type checking environment by finalizing pending trait + /// confirmations, folding types with the unification table, and collecting + /// diagnostics. + /// + /// # Arguments + /// + /// * `table` - A mutable reference to the unification table used for type + /// unification. + /// + /// # Returns + /// + /// * A tuple containing the `TypedBody` and a vector of `FuncBodyDiag`. + /// + /// The `TypedBody` includes the body of the function, pattern types, + /// expression types, and callables, all of which have been folded with + /// the unification table. + /// + /// The vector of `FuncBodyDiag` contains diagnostics related to function + /// bodies, such as ambiguous trait instances. pub(super) fn finish( mut self, table: &mut UnificationTable<'db>, @@ -249,6 +289,22 @@ impl<'db> TyCheckEnv<'db> { &self.var_env[idx] } + /// Performs pending trait confirmations and collects diagnostics. + /// + /// This function attempts to satisfy all pending trait confirmations by + /// iteratively probing and unifying trait instances until a fixed point + /// is reached. If any trait instance remains ambiguous, a diagnostic is + /// generated and added to the diagnostics vector. + /// + /// # Arguments + /// + /// * `prober` - A mutable reference to the [`Prober`] used for type + /// unification and probing. + /// + /// # Returns + /// + /// * A vector of `FuncBodyDiag` containing diagnostics related to ambiguous + /// trait instances. fn perform_pending_confirmation( &self, prober: &mut Prober<'db, '_>, diff --git a/crates/hir-analysis/src/ty/ty_check/pat.rs b/crates/hir-analysis/src/ty/ty_check/pat.rs index 4300c5588..33638c6c7 100644 --- a/crates/hir-analysis/src/ty/ty_check/pat.rs +++ b/crates/hir-analysis/src/ty/ty_check/pat.rs @@ -149,9 +149,19 @@ impl<'db> TyChecker<'db> { } } - ResolvedPathInBody::Binding(ident, _) | ResolvedPathInBody::NewBinding(ident) => { + ResolvedPathInBody::Binding(name, _) | ResolvedPathInBody::NewBinding(name) => { let binding = LocalBinding::local(pat, *is_mut); - self.env.register_pending_binding(ident, binding); + if let Some(LocalBinding::Local { + pat: conflict_with, .. + }) = self.env.register_pending_binding(name, binding) + { + let diag = BodyDiag::DuplicatedBinding { + primary: span.into(), + conflicat_with: conflict_with.lazy_span(self.body()).into(), + name, + }; + self.push_diag(diag); + } self.fresh_ty() } diff --git a/crates/uitest/fixtures/ty/trait_bound/coinductive.snap b/crates/uitest/fixtures/ty/trait_bound/coinductive.snap index 877a8de86..9ce6d1f2b 100644 --- a/crates/uitest/fixtures/ty/trait_bound/coinductive.snap +++ b/crates/uitest/fixtures/ty/trait_bound/coinductive.snap @@ -3,7 +3,7 @@ source: crates/uitest/tests/ty.rs expression: diags input_file: crates/uitest/fixtures/ty/trait_bound/coinductive.fe --- -error[8-0031]: type annotation is needed +error[8-0032]: type annotation is needed ┌─ coinductive.fe:35:9 │ 35 │ let v = Vec::new() @@ -11,5 +11,3 @@ error[8-0031]: type annotation is needed │ │ │ type annotation is needed │ consider giving `: Vec<_>` here - - diff --git a/crates/uitest/fixtures/ty_check/array.snap b/crates/uitest/fixtures/ty_check/array.snap index 4bf1680dd..101bd3645 100644 --- a/crates/uitest/fixtures/ty_check/array.snap +++ b/crates/uitest/fixtures/ty_check/array.snap @@ -27,7 +27,7 @@ error[8-0000]: type mismatch 5 │ let mut x: [i32; 5] = [1; 10] │ ^^^^^^^ expected `[i32; 5]`, but `[i32; 10]` is given -error[8-0031]: type annotation is needed +error[8-0032]: type annotation is needed ┌─ array.fe:3:14 │ 3 │ let z = [1, false, 1] @@ -36,7 +36,7 @@ error[8-0031]: type annotation is needed │ type annotation is needed │ no default type is provided for an integer type. consider giving integer type -error[8-0031]: type annotation is needed +error[8-0032]: type annotation is needed ┌─ array.fe:6:14 │ 6 │ let x = [1; false] diff --git a/crates/uitest/fixtures/ty_check/assign.snap b/crates/uitest/fixtures/ty_check/assign.snap index 51406833d..31e7409b7 100644 --- a/crates/uitest/fixtures/ty_check/assign.snap +++ b/crates/uitest/fixtures/ty_check/assign.snap @@ -15,13 +15,13 @@ error[8-0000]: type mismatch 36 │ t = 1 │ ^ expected `T`, but `{integer}` is given -error[8-0017]: not assignable left-hand side of assignment +error[8-0018]: not assignable left-hand side of assignment ┌─ assign.fe:31:5 │ 31 │ 1 = 1 │ ^ cant assign to this expression -error[8-0018]: left-hand side of assignment is immutable +error[8-0019]: left-hand side of assignment is immutable ┌─ assign.fe:21:9 │ 20 │ fn set_inner(self, x: i32, y: u32) { @@ -29,7 +29,7 @@ error[8-0018]: left-hand side of assignment is immutable 21 │ self.inner = Inner { x, y } │ ^^^^^^^^^^ immutable assignment -error[8-0018]: left-hand side of assignment is immutable +error[8-0019]: left-hand side of assignment is immutable ┌─ assign.fe:26:5 │ 25 │ fn foo(x: i32, mut y: u32, opt: Option, opt2: Option) { @@ -37,7 +37,7 @@ error[8-0018]: left-hand side of assignment is immutable 26 │ x = 1 │ ^ immutable assignment -error[8-0018]: left-hand side of assignment is immutable +error[8-0019]: left-hand side of assignment is immutable ┌─ assign.fe:43:13 │ 42 │ Some(x) => { @@ -45,7 +45,7 @@ error[8-0018]: left-hand side of assignment is immutable 43 │ x = 1 │ ^ immutable assignment -error[8-0031]: type annotation is needed +error[8-0032]: type annotation is needed ┌─ assign.fe:31:5 │ 31 │ 1 = 1 diff --git a/crates/uitest/fixtures/ty_check/aug_assign.snap b/crates/uitest/fixtures/ty_check/aug_assign.snap index 65f1ecda9..73ebb2c31 100644 --- a/crates/uitest/fixtures/ty_check/aug_assign.snap +++ b/crates/uitest/fixtures/ty_check/aug_assign.snap @@ -3,7 +3,7 @@ source: crates/uitest/tests/ty_check.rs expression: diags input_file: crates/uitest/fixtures/ty_check/aug_assign.fe --- -error[8-0016]: `std::ops::SubAssign` trait is not implemented +error[8-0017]: `std::ops::SubAssign` trait is not implemented ┌─ aug_assign.fe:6:5 │ 6 │ f -= f @@ -12,7 +12,7 @@ error[8-0016]: `std::ops::SubAssign` trait is not implemented │ `-=` cant be applied to `Foo` │ Try implementing `std::ops::SubAssign` for `Foo` -error[8-0018]: left-hand side of assignment is immutable +error[8-0019]: left-hand side of assignment is immutable ┌─ aug_assign.fe:7:5 │ 5 │ fn foo(f: Foo) { diff --git a/crates/uitest/fixtures/ty_check/binary.snap b/crates/uitest/fixtures/ty_check/binary.snap index 51f85487d..027a23451 100644 --- a/crates/uitest/fixtures/ty_check/binary.snap +++ b/crates/uitest/fixtures/ty_check/binary.snap @@ -3,7 +3,7 @@ source: crates/uitest/tests/ty_check.rs expression: diags input_file: crates/uitest/fixtures/ty_check/binary.fe --- -error[8-0016]: `std::ops::Add` trait is not implemented +error[8-0017]: `std::ops::Add` trait is not implemented ┌─ binary.fe:4:5 │ 4 │ f + f @@ -12,7 +12,7 @@ error[8-0016]: `std::ops::Add` trait is not implemented │ `+` cant be applied to `Foo` │ Try implementing `std::ops::Add` for `Foo` -error[8-0016]: `std::ops::And` trait is not implemented +error[8-0017]: `std::ops::And` trait is not implemented ┌─ binary.fe:6:6 │ 6 │ (f && f) || f @@ -21,7 +21,7 @@ error[8-0016]: `std::ops::And` trait is not implemented │ `&&` cant be applied to `Foo` │ Try implementing `std::ops::And` for `Foo` -error[8-0016]: `std::ops::Eq` trait is not implemented +error[8-0017]: `std::ops::Eq` trait is not implemented ┌─ binary.fe:7:5 │ 7 │ f == f @@ -30,7 +30,7 @@ error[8-0016]: `std::ops::Eq` trait is not implemented │ `==` cant be applied to `Foo` │ Try implementing `std::ops::Eq` for `Foo` -error[8-0016]: `std::ops::Ord` trait is not implemented +error[8-0017]: `std::ops::Ord` trait is not implemented ┌─ binary.fe:8:5 │ 8 │ f < f diff --git a/crates/uitest/fixtures/ty_check/call.snap b/crates/uitest/fixtures/ty_check/call.snap index 6093eadd4..6155cb773 100644 --- a/crates/uitest/fixtures/ty_check/call.snap +++ b/crates/uitest/fixtures/ty_check/call.snap @@ -15,7 +15,7 @@ error[8-0000]: type mismatch 17 │ make_tuple(false, 1) │ ^^^^^ expected `i32`, but `bool` is given -error[8-0024]: given argument label mismatch +error[8-0025]: given argument label mismatch ┌─ call.fe:6:9 │ 1 │ pub fn add(x: i32, y: i32) -> i32 { @@ -24,7 +24,7 @@ error[8-0024]: given argument label mismatch 6 │ add(1, 2) │ ^ expected `x` label -error[8-0024]: given argument label mismatch +error[8-0025]: given argument label mismatch ┌─ call.fe:6:12 │ 1 │ pub fn add(x: i32, y: i32) -> i32 { @@ -33,7 +33,7 @@ error[8-0024]: given argument label mismatch 6 │ add(1, 2) │ ^ expected `y` label -error[8-0024]: given argument label mismatch +error[8-0025]: given argument label mismatch ┌─ call.fe:7:9 │ 1 │ pub fn add(x: i32, y: i32) -> i32 { @@ -42,7 +42,7 @@ error[8-0024]: given argument label mismatch 7 │ add(y: 1, x: 2) │ ^ expected `x` label, but `y` given -error[8-0024]: given argument label mismatch +error[8-0025]: given argument label mismatch ┌─ call.fe:7:15 │ 1 │ pub fn add(x: i32, y: i32) -> i32 { @@ -51,7 +51,7 @@ error[8-0024]: given argument label mismatch 7 │ add(y: 1, x: 2) │ ^ expected `y` label, but `x` given -error[8-0024]: given argument label mismatch +error[8-0025]: given argument label mismatch ┌─ call.fe:8:15 │ 1 │ pub fn add(x: i32, y: i32) -> i32 { diff --git a/crates/uitest/fixtures/ty_check/field_access.snap b/crates/uitest/fixtures/ty_check/field_access.snap index 98c61b0fe..6a13843b4 100644 --- a/crates/uitest/fixtures/ty_check/field_access.snap +++ b/crates/uitest/fixtures/ty_check/field_access.snap @@ -3,25 +3,25 @@ source: crates/uitest/tests/ty_check.rs expression: diags input_file: crates/uitest/fixtures/ty_check/field_access.fe --- -error[8-0014]: type must be known here +error[8-0015]: type must be known here ┌─ field_access.fe:7:5 │ 7 │ x.1 │ ^ type must be known here -error[8-0015]: invalid field index +error[8-0016]: invalid field index ┌─ field_access.fe:2:5 │ 2 │ x.2 │ ^^^ field `2` is not found in `(i32, u32)` -error[8-0015]: invalid field index +error[8-0016]: invalid field index ┌─ field_access.fe:16:5 │ 16 │ bar.v │ ^^^^^ field `v` is not found in `Bar` -error[8-0031]: type annotation is needed +error[8-0032]: type annotation is needed ┌─ field_access.fe:6:9 │ 6 │ let x diff --git a/crates/uitest/fixtures/ty_check/for_.snap b/crates/uitest/fixtures/ty_check/for_.snap index e5441d3f5..7e0b58be0 100644 --- a/crates/uitest/fixtures/ty_check/for_.snap +++ b/crates/uitest/fixtures/ty_check/for_.snap @@ -9,7 +9,7 @@ error[8-0000]: type mismatch 16 │ for Bar { x } in foo_arr { │ ^^^^^^^^^ expected `Foo`, but `Bar` is given -error[8-0018]: left-hand side of assignment is immutable +error[8-0019]: left-hand side of assignment is immutable ┌─ for_.fe:17:9 │ 15 │ let res = 0 @@ -18,7 +18,7 @@ error[8-0018]: left-hand side of assignment is immutable 17 │ res += x │ ^^^ immutable assignment -error[8-0020]: `Iterator` needs to be implemented for Foo +error[8-0021]: `Iterator` needs to be implemented for Foo ┌─ for_.fe:11:14 │ 11 │ for i in foo { } diff --git a/crates/uitest/fixtures/ty_check/index.snap b/crates/uitest/fixtures/ty_check/index.snap index ebdbca100..7bde51f63 100644 --- a/crates/uitest/fixtures/ty_check/index.snap +++ b/crates/uitest/fixtures/ty_check/index.snap @@ -9,7 +9,7 @@ error[8-0000]: type mismatch 4 │ x[false] │ ^^^^^ expected `u256`, but `bool` is given -error[8-0016]: `std::ops::Index` trait is not implemented +error[8-0017]: `std::ops::Index` trait is not implemented ┌─ index.fe:6:5 │ 6 │ f[1] diff --git a/crates/uitest/fixtures/ty_check/loop_control.snap b/crates/uitest/fixtures/ty_check/loop_control.snap index f02e20c16..5f35e9055 100644 --- a/crates/uitest/fixtures/ty_check/loop_control.snap +++ b/crates/uitest/fixtures/ty_check/loop_control.snap @@ -3,13 +3,13 @@ source: crates/uitest/tests/ty_check.rs expression: diags input_file: crates/uitest/fixtures/ty_check/loop_control.fe --- -error[8-0019]: `continue` is not allowed outside of a loop +error[8-0020]: `continue` is not allowed outside of a loop ┌─ loop_control.fe:2:5 │ 2 │ continue │ ^^^^^^^^ `continue` is not allowed here -error[8-0019]: `break` is not allowed outside of a loop +error[8-0020]: `break` is not allowed outside of a loop ┌─ loop_control.fe:3:5 │ 3 │ break diff --git a/crates/uitest/fixtures/ty_check/method_selection/ambiguous_inherent_method.snap b/crates/uitest/fixtures/ty_check/method_selection/ambiguous_inherent_method.snap index 3594cfff3..400897539 100644 --- a/crates/uitest/fixtures/ty_check/method_selection/ambiguous_inherent_method.snap +++ b/crates/uitest/fixtures/ty_check/method_selection/ambiguous_inherent_method.snap @@ -3,7 +3,7 @@ source: crates/uitest/tests/ty_check.rs expression: diags input_file: crates/uitest/fixtures/ty_check/method_selection/ambiguous_inherent_method.fe --- -error[8-0025]: ambiguous method call +error[8-0026]: ambiguous method call ┌─ ambiguous_inherent_method.fe:35:7 │ 22 │ fn foo(self) -> i32 { @@ -15,7 +15,7 @@ error[8-0025]: ambiguous method call 35 │ f.foo() │ ^^^ `foo` is ambiguous -error[8-0031]: type annotation is needed +error[8-0032]: type annotation is needed ┌─ ambiguous_inherent_method.fe:34:9 │ 34 │ let f = Foo::default() diff --git a/crates/uitest/fixtures/ty_check/method_selection/ambiguous_trait_def.snap b/crates/uitest/fixtures/ty_check/method_selection/ambiguous_trait_def.snap index fac49f0d5..d2d28b74a 100644 --- a/crates/uitest/fixtures/ty_check/method_selection/ambiguous_trait_def.snap +++ b/crates/uitest/fixtures/ty_check/method_selection/ambiguous_trait_def.snap @@ -3,7 +3,7 @@ source: crates/uitest/tests/ty_check.rs expression: diags input_file: crates/uitest/fixtures/ty_check/method_selection/ambiguous_trait_def.fe --- -error[8-0026]: multiple trait candidates found +error[8-0027]: multiple trait candidates found ┌─ ambiguous_trait_def.fe:38:15 │ 38 │ let y = f.foo() @@ -13,7 +13,7 @@ error[8-0026]: multiple trait candidates found │ candidate: `Trait2::foo` │ candidate: `Trait1::foo` -error[8-0031]: type annotation is needed +error[8-0032]: type annotation is needed ┌─ ambiguous_trait_def.fe:37:9 │ 37 │ let f = Foo::new() diff --git a/crates/uitest/fixtures/ty_check/method_selection/ambiguous_trait_inst.snap b/crates/uitest/fixtures/ty_check/method_selection/ambiguous_trait_inst.snap index bb631a43a..57097835d 100644 --- a/crates/uitest/fixtures/ty_check/method_selection/ambiguous_trait_inst.snap +++ b/crates/uitest/fixtures/ty_check/method_selection/ambiguous_trait_inst.snap @@ -3,7 +3,7 @@ source: crates/uitest/tests/ty_check.rs expression: diags input_file: crates/uitest/fixtures/ty_check/method_selection/ambiguous_trait_inst.fe --- -error[8-0027]: ambiguous trait implementation +error[8-0028]: ambiguous trait implementation ┌─ ambiguous_trait_inst.fe:23:13 │ 23 │ let y = f.foo() @@ -13,7 +13,7 @@ error[8-0027]: ambiguous trait implementation │ candidate: Trait │ candidate: Trait -error[8-0031]: type annotation is needed +error[8-0032]: type annotation is needed ┌─ ambiguous_trait_inst.fe:23:9 │ 23 │ let y = f.foo() diff --git a/crates/uitest/fixtures/ty_check/method_selection/require_explicit_import.snap b/crates/uitest/fixtures/ty_check/method_selection/require_explicit_import.snap index 892cb7c47..32d67c6ea 100644 --- a/crates/uitest/fixtures/ty_check/method_selection/require_explicit_import.snap +++ b/crates/uitest/fixtures/ty_check/method_selection/require_explicit_import.snap @@ -3,7 +3,7 @@ source: crates/uitest/tests/ty_check.rs expression: diags input_file: crates/uitest/fixtures/ty_check/method_selection/require_explicit_import.fe --- -error[8-0028]: trait is not in the scope +error[8-0029]: trait is not in the scope ┌─ require_explicit_import.fe:2:7 │ 2 │ x.foo() diff --git a/crates/uitest/fixtures/ty_check/pat/duplicated_binding.fe b/crates/uitest/fixtures/ty_check/pat/duplicated_binding.fe new file mode 100644 index 000000000..74a15a9ea --- /dev/null +++ b/crates/uitest/fixtures/ty_check/pat/duplicated_binding.fe @@ -0,0 +1,11 @@ +pub enum E { + V(i32, u32) +} + +fn foo(f: E) { + let E::V(x, x) = f + + match f { + E::V(x, x) => () + } +} diff --git a/crates/uitest/fixtures/ty_check/pat/duplicated_binding.snap b/crates/uitest/fixtures/ty_check/pat/duplicated_binding.snap new file mode 100644 index 000000000..57b8745e6 --- /dev/null +++ b/crates/uitest/fixtures/ty_check/pat/duplicated_binding.snap @@ -0,0 +1,22 @@ +--- +source: crates/uitest/tests/ty_check.rs +expression: diags +input_file: crates/uitest/fixtures/ty_check/pat/duplicated_binding.fe +--- +error[8-0002]: duplicated bidning `x` in the same pattern + ┌─ duplicated_binding.fe:6:17 + │ +6 │ let E::V(x, x) = f + │ - ^ `x` is already defined in the same pattern + │ │ + │ `x` is defined here + +error[8-0002]: duplicated bidning `x` in the same pattern + ┌─ duplicated_binding.fe:9:17 + │ +9 │ E::V(x, x) => () + │ - ^ `x` is already defined in the same pattern + │ │ + │ `x` is defined here + + diff --git a/crates/uitest/fixtures/ty_check/pat/path.snap b/crates/uitest/fixtures/ty_check/pat/path.snap index 5360547d5..d14a02086 100644 --- a/crates/uitest/fixtures/ty_check/pat/path.snap +++ b/crates/uitest/fixtures/ty_check/pat/path.snap @@ -3,7 +3,7 @@ source: crates/uitest/tests/ty_check.rs expression: diags input_file: crates/uitest/fixtures/ty_check/pat/path.fe --- -error[8-0004]: expected unit variant +error[8-0005]: expected unit variant ┌─ path.fe:7:13 │ 7 │ let x = Foo diff --git a/crates/uitest/fixtures/ty_check/pat/path_tuple.snap b/crates/uitest/fixtures/ty_check/pat/path_tuple.snap index fe07c178c..720b3b5d8 100644 --- a/crates/uitest/fixtures/ty_check/pat/path_tuple.snap +++ b/crates/uitest/fixtures/ty_check/pat/path_tuple.snap @@ -3,7 +3,7 @@ source: crates/uitest/tests/ty_check.rs expression: diags input_file: crates/uitest/fixtures/ty_check/pat/path_tuple.fe --- -error[8-0004]: expected unit variant +error[8-0005]: expected unit variant ┌─ path_tuple.fe:12:9 │ 12 │ let Foo::Variant @@ -12,7 +12,7 @@ error[8-0004]: expected unit variant │ expected unit variant here, but found tuple variant │ Consider using `Foo::Variant(_, _)` instead -error[8-0005]: expected tuple variant +error[8-0006]: expected tuple variant ┌─ path_tuple.fe:13:9 │ 13 │ let Foo::Variant2(x, y) @@ -21,25 +21,25 @@ error[8-0005]: expected tuple variant │ expected tuple variant here, but found unit variant │ Consider using `Foo::Variant2` instead -error[8-0007]: field count mismatch +error[8-0008]: field count mismatch ┌─ path_tuple.fe:7:9 │ 7 │ let Foo::Variant(x, y, z) │ ^^^^^^^^^^^^^^^^^^^^^ expected 2 fields here, but 3 given -error[8-0007]: field count mismatch +error[8-0008]: field count mismatch ┌─ path_tuple.fe:8:9 │ 8 │ let Foo::Variant(.., x, y, z) │ ^^^^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields here, but 3 given -error[8-0007]: field count mismatch +error[8-0008]: field count mismatch ┌─ path_tuple.fe:9:9 │ 9 │ let Foo::Variant(x, .., y, z) │ ^^^^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields here, but 3 given -error[8-0007]: field count mismatch +error[8-0008]: field count mismatch ┌─ path_tuple.fe:10:9 │ 10 │ let Foo::Variant(x, y, z, ..) diff --git a/crates/uitest/fixtures/ty_check/pat/record.snap b/crates/uitest/fixtures/ty_check/pat/record.snap index 0f59b5556..4e5157b4e 100644 --- a/crates/uitest/fixtures/ty_check/pat/record.snap +++ b/crates/uitest/fixtures/ty_check/pat/record.snap @@ -3,19 +3,35 @@ source: crates/uitest/tests/ty_check.rs expression: diags input_file: crates/uitest/fixtures/ty_check/pat/record.fe --- -error[8-0002]: duplicated `..` found +error[8-0002]: duplicated bidning `x` in the same pattern + ┌─ record.fe:12:17 + │ +12 │ let Foo {x, x} + │ - ^ `x` is already defined in the same pattern + │ │ + │ `x` is defined here + +error[8-0002]: duplicated bidning `x` in the same pattern + ┌─ record.fe:18:26 + │ +18 │ let Bar::Variant {x, x} + │ - ^ `x` is already defined in the same pattern + │ │ + │ `x` is defined here + +error[8-0003]: duplicated `..` found ┌─ record.fe:13:24 │ 13 │ let Foo {x, .., y, ..} │ ^^ `..` can be used only once -error[8-0002]: duplicated `..` found +error[8-0003]: duplicated `..` found ┌─ record.fe:19:33 │ 19 │ let Bar::Variant {x, .., y, ..} │ ^^ `..` can be used only once -error[8-0008]: duplicated record field binding +error[8-0009]: duplicated record field binding ┌─ record.fe:12:17 │ 12 │ let Foo {x, x} @@ -23,7 +39,7 @@ error[8-0008]: duplicated record field binding │ │ │ first use of `x` -error[8-0008]: duplicated record field binding +error[8-0009]: duplicated record field binding ┌─ record.fe:18:26 │ 18 │ let Bar::Variant {x, x} @@ -31,19 +47,19 @@ error[8-0008]: duplicated record field binding │ │ │ first use of `x` -error[8-0009]: specified field not found +error[8-0010]: specified field not found ┌─ record.fe:14:17 │ 14 │ let Foo {x, z} │ ^ field `z` not found -error[8-0009]: specified field not found +error[8-0010]: specified field not found ┌─ record.fe:20:26 │ 20 │ let Bar::Variant {x, z} │ ^ field `z` not found -error[8-0010]: explicit label is required +error[8-0011]: explicit label is required ┌─ record.fe:15:17 │ 15 │ let Foo {x, Bar::Unit} @@ -52,7 +68,7 @@ error[8-0010]: explicit label is required │ explicit label is required │ Consider using `Foo { x, y }` instead -error[8-0010]: explicit label is required +error[8-0011]: explicit label is required ┌─ record.fe:21:26 │ 21 │ let Bar::Variant {x, Bar::Unit} @@ -61,7 +77,7 @@ error[8-0010]: explicit label is required │ explicit label is required │ Consider using `Bar::Variant { x, y }` instead -error[8-0011]: all fields are not given +error[8-0012]: all fields are not given ┌─ record.fe:16:13 │ 16 │ let Foo {x} @@ -70,7 +86,7 @@ error[8-0011]: all fields are not given │ missing `y` │ Consider using `Foo { x, y }` instead -error[8-0011]: all fields are not given +error[8-0012]: all fields are not given ┌─ record.fe:22:22 │ 22 │ let Bar::Variant {} diff --git a/crates/uitest/fixtures/ty_check/ret.snap b/crates/uitest/fixtures/ty_check/ret.snap index 79d9822e6..011d01452 100644 --- a/crates/uitest/fixtures/ty_check/ret.snap +++ b/crates/uitest/fixtures/ty_check/ret.snap @@ -9,7 +9,7 @@ error[8-0000]: type mismatch 15 │ false │ ^^^^^ expected `{integer}`, but `bool` is given -error[8-0013]: returned type mismatch +error[8-0014]: returned type mismatch ┌─ ret.fe:2:5 │ 1 │ fn foo1() { @@ -17,7 +17,7 @@ error[8-0013]: returned type mismatch 2 │ return false │ ^^^^^^^^^^^^ expected `()`, but `bool` is returned -error[8-0013]: returned type mismatch +error[8-0014]: returned type mismatch ┌─ ret.fe:6:5 │ 5 │ fn foo2() -> i32 { diff --git a/crates/uitest/fixtures/ty_check/tuple.snap b/crates/uitest/fixtures/ty_check/tuple.snap index d18f3611a..665c191af 100644 --- a/crates/uitest/fixtures/ty_check/tuple.snap +++ b/crates/uitest/fixtures/ty_check/tuple.snap @@ -15,7 +15,7 @@ error[8-0000]: type mismatch 4 │ let y: (i32, bool) = (1, 2) │ ^ expected `bool`, but `{integer}` is given -error[8-0031]: type annotation is needed +error[8-0032]: type annotation is needed ┌─ tuple.fe:2:32 │ 2 │ let x: (i32, u32, bool) = (1, 2) @@ -24,7 +24,7 @@ error[8-0031]: type annotation is needed │ type annotation is needed │ no default type is provided for an integer type. consider giving integer type -error[8-0031]: type annotation is needed +error[8-0032]: type annotation is needed ┌─ tuple.fe:2:35 │ 2 │ let x: (i32, u32, bool) = (1, 2) diff --git a/crates/uitest/fixtures/ty_check/unary.snap b/crates/uitest/fixtures/ty_check/unary.snap index 33cb5f0c6..a9cd7fd34 100644 --- a/crates/uitest/fixtures/ty_check/unary.snap +++ b/crates/uitest/fixtures/ty_check/unary.snap @@ -3,7 +3,7 @@ source: crates/uitest/tests/ty_check.rs expression: diags input_file: crates/uitest/fixtures/ty_check/unary.fe --- -error[8-0016]: `std::ops::UnaryPlus` trait is not implemented +error[8-0017]: `std::ops::UnaryPlus` trait is not implemented ┌─ unary.fe:5:5 │ 5 │ +f @@ -12,7 +12,7 @@ error[8-0016]: `std::ops::UnaryPlus` trait is not implemented │ `+` cant be applied to `Foo` │ Try implementing `std::ops::UnaryPlus` for `Foo` -error[8-0016]: `std::ops::Neg` trait is not implemented +error[8-0017]: `std::ops::Neg` trait is not implemented ┌─ unary.fe:6:5 │ 6 │ -f @@ -21,7 +21,7 @@ error[8-0016]: `std::ops::Neg` trait is not implemented │ `-` cant be applied to `Foo` │ Try implementing `std::ops::Neg` for `Foo` -error[8-0016]: `std::ops::Not` trait is not implemented +error[8-0017]: `std::ops::Not` trait is not implemented ┌─ unary.fe:7:5 │ 7 │ !f