Skip to content

Commit

Permalink
Reject annotations on ivars defined in base class (#9502)
Browse files Browse the repository at this point in the history
  • Loading branch information
waj authored Jul 6, 2020
1 parent 794a98a commit e7db73f
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 1 deletion.
19 changes: 18 additions & 1 deletion spec/compiler/semantic/annotation_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ describe "Semantic: annotation" do
end
def foo
{% if @type.instance_vars.first.annotations(Foo) %}
{% if @type.instance_vars.first.annotation(Foo) %}
1
{% else %}
'a'
Expand Down Expand Up @@ -918,6 +918,23 @@ describe "Semantic: annotation" do
end
end

it "errors when annotate instance variable in subclass" do
assert_error %(
annotation Foo
end
class Base
@x : Nil
end
class Child < Base
@[Foo]
@x : Nil
end
),
"can't annotate @x in Child because it was first defined in Base"
end

it "errors if wanting to add type inside annotation (1) (#8614)" do
assert_error %(
annotation Ann
Expand Down
5 changes: 5 additions & 0 deletions src/compiler/crystal/semantic/type_declaration_processor.cr
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@ struct Crystal::TypeDeclarationProcessor
unless supervar.type.same?(type_decl.type)
raise TypeException.new("instance variable '#{name}' of #{supervar.owner}, with #{owner} < #{supervar.owner}, is already declared as #{supervar.type} (trying to re-declare as #{type_decl.type})", type_decl.location)
end

# Reject annotations to existing instance var
type_decl.annotations.try &.each do |_, ann|
ann.raise "can't annotate #{name} in #{owner} because it was first defined in #{supervar.owner}"
end
else
declare_meta_type_var(owner.instance_vars, owner, name, type_decl, instance_var: true, check_nilable: !owner.module?)
remove_error owner, name
Expand Down

0 comments on commit e7db73f

Please sign in to comment.