Files
Nim/tests/specialops/terrmsgs.nim
metagn 4d9e5e8b6d fix field setter fallback that never worked (#24871)
refs https://forum.nim-lang.org/t/12785, refs #4711

The code was already there that when `propertyWriteAccess` returns `nil`
(i.e. cannot find a setter), `semAsgn` turns the [LHS into a call and
semchecks
it](1ef9a656d2/compiler/semexprs.nim (L1941-L1948)),
meaning if a setter cannot be found a getter will be assigned to
instead. However `propertyWriteAccess` never returned nil, because
`semOverloadedCallAnalyseEffects` was not called with `efNoUndeclared`
and so produced an error directly. So `efNoUndeclared` is passed to this
call so this code works as intended.

This fixes the issue described in #4711 which was closed because
subscripts do not have the same behavior implemented. However we can
implement this for subscripts as well (I have an implementation ready),
it just changes the error message from the failed overloads of `[]=` to
the failed overloads of `[]` for the LHS, which might be misleading but
is consistent with the error messages for any other assignment. I can do
this in this PR or another one.
2025-04-13 19:21:33 +02:00

76 lines
2.0 KiB
Nim

discard """
action: reject
cmd: '''nim check $options $file'''
matrix: "; -d:testWithout; --mm:refc"
"""
when not defined(testWithout): # test for same errors before and after
{.experimental: "dotOperators".}
{.experimental: "callOperator".}
# issue #13063
block:
type Foo = object
type Bar = object
x1: int
var b: Bar
block:
template `.`(a: Foo, b: untyped): untyped = 123
echo b.x #[tt.Error
^ undeclared field: 'x' for type terrmsgs.Bar [type declared in terrmsgs.nim(15, 8)]]#
block:
template `.()`(a: Foo, b: untyped): untyped = 123
echo b.x() #[tt.Error
^ attempting to call undeclared routine: 'x']#
block:
template `.=`(a: Foo, b: untyped, c: untyped) = b = c
b.x = 123 #[tt.Error
^ undeclared field: 'x' for type terrmsgs.Bar [type declared in terrmsgs.nim(15, 8)]]#
block:
template `()`(a: Foo, b: untyped, c: untyped) = echo "something"
# completely undeclared::
xyz(123) #[tt.Error
^ undeclared identifier: 'xyz']#
# already declared routine:
min(123) #[tt.Error
^ type mismatch: got <int literal(123)>]#
# non-routine type shows `()` overloads:
b(123) #[tt.Error
^ attempting to call routine: 'b']#
echo b.x #[tt.Error
^ undeclared field: 'x' for type terrmsgs.Bar [type declared in terrmsgs.nim(15, 8)]]#
echo b.x() #[tt.Error
^ attempting to call undeclared routine: 'x']#
# issue #7777
import macros
block:
type TestType = object
private_field: string
when false:
template getField(obj, field: untyped): untyped = obj.field
macro `.`(obj: TestType, field: untyped): untyped =
let private = newIdentNode("private_" & $field)
result = quote do:
`obj`.getField(`private`) #[tt.Error
^ attempting to call undeclared routine: 'getField']#
var tt: TestType
discard tt.field
block: # related to issue #6981
proc `()`(a:string, b:string):string = a & b
proc mewSeq[T](a,b:int)=discard
proc mewSeq[T](c:int)= discard
mewSeq[int]() #[tt.Error
^ type mismatch: got <>]#