ernie-research/MEnvData-SWE huggingface dataset:
Repository: Shopify/liquid (Ruby)

Issue:
Unexpected end tags are reported as unknown, which confuses new users
I've had a few instances of helping out new users who get stuck when code like this:

{% if thing %}hello{% endunless %}

Reports this error:
Liquid syntax error: Unknown tag 'endunless'

This happens when someone half-changes their unless block to an if block.

I'd say the tag is more unexpected there than completely unknown, and it might be better for liquid to check if the unexpected tag starts with end and is the end of a known block before reporting the error in this case



Discussion:
We have an error message specifically for an unknown `end` tag, but maybe that should be for any unknown tag that starts with `end`.  That would result in an error message of `Liquid syntax error: 'endunless' is not a valid delimiter for if tags. use endif` which seems like it would be appropriate



Patch:
diff --git a/lib/liquid/block.rb b/lib/liquid/block.rb
index d9547c783..00c59b2d1 100644
--- a/lib/liquid/block.rb
+++ b/lib/liquid/block.rb
@@ -26,12 +26,12 @@ def nodelist
     end
 
     def unknown_tag(tag, _params, _tokens)
-      case tag
-      when 'else'.freeze
+      if tag == 'else'.freeze
         raise SyntaxError.new(parse_context.locale.t("errors.syntax.unexpected_else".freeze,
           block_name: block_name))
-      when 'end'.freeze
+      elsif tag.start_with?('end'.freeze)
         raise SyntaxError.new(parse_context.locale.t("errors.syntax.invalid_delimiter".freeze,
+          tag: tag,
           block_name: block_name,
           block_delimiter: block_delimiter))
       else
diff --git a/lib/liquid/locales/en.yml b/lib/liquid/locales/en.yml
index 9a259bf11..48b3b1d83 100644
--- a/lib/liquid/locales/en.yml
+++ b/lib/liquid/locales/en.yml
@@ -14,7 +14,7 @@
       if: "Syntax Error in tag 'if' - Valid syntax: if [expression]"
       include: "Error in tag 'include' - Valid syntax: include '[template]' (with|for) [object|collection]"
       unknown_tag: "Unknown tag '%{tag}'"
-      invalid_delimiter: "'end' is not a valid delimiter for %{block_name} tags. use %{block_delimiter}"
+      invalid_delimiter: "'%{tag}' is not a valid delimiter for %{block_name} tags. use %{block_delimiter}"
       unexpected_else: "%{block_name} tag does not expect 'else' tag"
       unexpected_outer_tag: "Unexpected outer '%{tag}' tag"
       tag_termination: "Tag '%{token}' was not properly terminated with regexp: %{tag_end}"


Test patch:
diff --git a/test/integration/block_test.rb b/test/integration/block_test.rb
new file mode 100644
index 000000000..082453016
--- /dev/null
+++ b/test/integration/block_test.rb
@@ -0,0 +1,12 @@
+require 'test_helper'
+
+class BlockTest < Minitest::Test
+  include Liquid
+
+  def test_unexpected_end_tag
+    exc = assert_raises(SyntaxError) do
+      Template.parse("{% if true %}{% endunless %}")
+    end
+    assert_equal exc.message, "Liquid syntax error: 'endunless' is not a valid delimiter for if tags. use endif"
+  end
+end
Repository: fakefs/fakefs (Ruby)

Issue:
Dir.children includes . and ..
When using FakeFS, `Dir.new('.').children` includes `.` and `..`.

As per the [docs](https://docs.ruby-lang.org/en/master/Dir.html#method-i-children) they shouldn't be included:

> Returns an array of the entry names in self except for '.' and '..'

I think in [line 43](https://github.com/fakefs/fakefs/blob/a3f1b9399d8695ad87a92ee751add0616b13f179/lib/fakefs/dir.rb#L43) you need to reject `.` and `..`.


Discussion:
sounds good, can you make a PR to fix ?



Patch:
diff --git a/lib/fakefs/dir.rb b/lib/fakefs/dir.rb
index 2c4d01d..6c80888 100644
--- a/lib/fakefs/dir.rb
+++ b/lib/fakefs/dir.rb
@@ -40,7 +40,7 @@ def each
     end
 
     def children
-      each.to_a
+      each.reject { |entry_name| entry_name == '.' || entry_name == '..' }.to_a
     end
 
     def pos


Test patch:
diff --git a/test/fakefs_test.rb b/test/fakefs_test.rb
index 5e15a95..107a66b 100644
--- a/test/fakefs_test.rb
+++ b/test/fakefs_test.rb
@@ -3267,7 +3267,7 @@ def test_directory_open
   end
 
   def test_directory_open_block
-    test = ['.', '..', 'file_1', 'file_2', 'file_3', 'file_4', 'file_5']
+    test = ['file_1', 'file_2', 'file_3', 'file_4', 'file_5']
 
     FileUtils.mkdir_p('/this/path/should/be/here')
 
@@ -3278,7 +3278,7 @@ def test_directory_open_block
     children = Dir.open('/this/path/should/be/here') do |dir|
       dir.children
     end
-
+      
     assert children.size == test.size
     test.each { |t| assert children.include?(t) }
   end
Repository: ffaker/ffaker (Ruby)

Issue:
Invalid canadian postal codes
The logic used to generate canadian zipcodes is wrong. The current format mask is this: `'?#? #?#'`. However, not all letters are valid in all the positions, so calling `bothify` on that may return invalid postal codes.

Valid canadian postal codes should match this regexp: `/^[A-CEGHJK-NPR-TVXY][0-9][A-CEGHJK-NPR-TV-Z] [0-9][A-CEGHJK-NPR-TV-Z][0-9]$/`

If you wish, I will fork this repo and implement the necessary changes. I just wanted to open the issue to see if something like this would be merged, and to link the PR back to the issue for discussion.



Discussion:
Hopefully @steveclarke knows more, he made the first implementation. :+1: 
It would be great if you could create a fix-branch and a PR if the postal codes are wrong generated. :gift: 

I will take this.




Patch:
diff --git a/lib/ffaker/address_ca.rb b/lib/ffaker/address_ca.rb
index e15614f4..5fbaffcd 100644
--- a/lib/ffaker/address_ca.rb
+++ b/lib/ffaker/address_ca.rb
@@ -9,11 +9,12 @@ module AddressCA
     extend ModuleUtils
     extend self
 
-    POSTAL_CODE_FORMATS = ['?#? #?#']
+    POSTAL_CODE_FORMAT = '?#? #?#'
+    POSTAL_CODE_CHARS = %w(A B C E G H J K L M N P R S T V X Y)
     PROVINCE_ABBRS = %w(NL NS PE NB QC ON MB SK AB BC YT NT NU)
 
     def postal_code
-      FFaker.bothify(POSTAL_CODE_FORMATS.sample).upcase
+      FFaker.numerify(POSTAL_CODE_FORMAT.gsub("?") { POSTAL_CODE_CHARS.sample })
     end
 
     def province
@@ -27,6 +28,5 @@ def city
     def province_abbr
       PROVINCE_ABBRS.sample
     end
-
   end
 end


Test patch:
diff --git a/test/test_address_ca.rb b/test/test_address_ca.rb
index b7e26da3..1f2e6434 100644
--- a/test/test_address_ca.rb
+++ b/test/test_address_ca.rb
@@ -4,18 +4,20 @@
 
 class TestAddressCA < Test::Unit::TestCase
   def test_province
-    assert_match /[ a-z]/, FFaker::AddressCA.province
+    assert_match(/\A[ a-z]+\z/i, FFaker::AddressCA.province)
   end
 
   def test_province_abbr
-    assert_match /[A-Z][A-Z]/, FFaker::AddressCA.province_abbr
+    assert_match(/\A[A-Z]{2}\z/, FFaker::AddressCA.province_abbr)
   end
 
   def test_city
-    assert FFaker::AddressCA::CITY.include?(FFaker::AddressCA.city)
+    assert_include(FFaker::AddressCA::CITY, FFaker::AddressCA.city)
   end
 
   def test_postal_code
-    assert_match /[A-Z]\d[A-Z]\W\d[A-Z]\d/, FFaker::AddressCA.postal_code
+    assert_match(
+      /\A[A-CEGHJK-NPR-TVXY]\d[A-CEGHJK-NPR-TV-Z] \d[A-CEGHJK-NPR-TV-Z]\d\z/,
+      FFaker::AddressCA.postal_code)
   end
 end
Repository: ruby/psych (Ruby)

Issue:
Double quotes (2)
When emitting YAML using Psych, strings that have a key-value pair where the value contains a colon and a single quote, Psych escapes the single quote with another single quote, relates to #157.

I'd expect
`Psych.dump(key: "me: I don't think so")`
to return
`"---\n:key: \"me: I don't think so\"\n"`
It actually returns
`"---\n:key: 'me: I don''t think so'\n"`

This is not a huge issue but confuses people.


Discussion:

Patch:
diff --git a/lib/psych/visitors/yaml_tree.rb b/lib/psych/visitors/yaml_tree.rb
index cfed8f18..f44e973c 100644
--- a/lib/psych/visitors/yaml_tree.rb
+++ b/lib/psych/visitors/yaml_tree.rb
@@ -304,7 +304,7 @@ def visit_String o
           quote = false
         elsif @line_width && o.length > @line_width
           style = Nodes::Scalar::FOLDED
-        elsif o =~ /^[^[:word:]][^"]*$/
+        elsif o =~ /^[^[:word:]][^"]*$/ or o =~ /^([^"]*'+[^"]*)+$/
           style = Nodes::Scalar::DOUBLE_QUOTED
         elsif not String === @ss.tokenize(o) or /\A0[0-7]*[89]/ =~ o
           style = Nodes::Scalar::SINGLE_QUOTED


Test patch:
diff --git a/test/psych/test_string.rb b/test/psych/test_string.rb
index 973f38b9..e80d1919 100644
--- a/test/psych/test_string.rb
+++ b/test/psych/test_string.rb
@@ -37,6 +37,13 @@ def test_doublequotes_when_there_is_a_single
       assert_equal str, Psych.load(yaml)
     end
 
+    def test_doublequotes_when_there_are_single_quotes_only
+      str = "psych: Please don't escape ' with ' here."
+      yaml = Psych.dump str
+      assert_equal "--- \"psych: Please don't escape ' with ' here.\"\n", yaml
+      assert_equal str, Psych.load(yaml)
+    end
+
     def test_plain_when_shorten_than_line_width_and_no_final_line_break
       str = "Lorem ipsum"
       yaml = Psych.dump str, line_width: 12
Repository: newrelic/newrelic-ruby-agent (Ruby)

Issue:
Sidekiq error: NameError: undefined local variable or method `headers' for NewRelic::Agent::DistributedTracing:Module
## Description

The following exception is logged repeatedly from our Sidekiq workers. This does not break metric reporting, and the exception is catched somewhere in the New Relic code.

## Expected Behavior

No exception in logs.

## Troubleshooting

 We have not configured Distributed tracing, beyond enabling it in the config file:

```
common: &default_settings
  distributed_tracing:
    enabled: true
```

The log message reads

```
ERROR : error during accept_distributed_trace_headers
ERROR : NameError: undefined local variable or method `headers' for NewRelic::Agent::DistributedTracing:Module
```

## Steps to Reproduce

Enable distributed tracing, then run a Sidekiq job.

## Your Environment

```
newrelic_rpm (6.15.0)
sidekiq (6.0.6)
```



Discussion:
@leonid-shevtsov Thanks for reporting this issue.  There's a typo in the method that checks that the parameters passed to the `accept_distributed_trace_headers` API call are of the expected type.   In this case, the first method parameter, `headers`  is expected to be a `Hash` object.  The validation check had a typo leftover from refactoring effort and is resolved by PR #558 and will appear in the next release of the agent.



Patch:
diff --git a/lib/new_relic/supportability_helper.rb b/lib/new_relic/supportability_helper.rb
index 7fe7b7c5fa..927e7cfc07 100644
--- a/lib/new_relic/supportability_helper.rb
+++ b/lib/new_relic/supportability_helper.rb
@@ -74,7 +74,7 @@ def valid_api_argument_class? arg, name, klass
       caller_location = caller_locations.first.label
 
       message = "Bad argument passed to ##{caller_location}. " \
-        "Expected #{klass} for `#{name}` but got #{headers.class}"
+        "Expected #{klass} for `#{name}` but got #{arg.class}"
 
       NewRelic::Agent.logger.warn message
       nil


Test patch:
diff --git a/test/new_relic/supportability_helper_test.rb b/test/new_relic/supportability_helper_test.rb
new file mode 100644
index 0000000000..e983897d2d
--- /dev/null
+++ b/test/new_relic/supportability_helper_test.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+# This file is distributed under New Relic's license terms.
+# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
+
+require File.expand_path(File.join(File.dirname(__FILE__),'..','test_helper'))
+
+class NewRelic::SupportabilityHelperTest < Minitest::Test
+
+  def teardown
+    NewRelic::Agent.shutdown
+    super
+  end
+
+  include NewRelic::SupportabilityHelper
+
+  def test_valid_api_argument_class_truthy
+    assert valid_api_argument_class?({foo: :bar}, "headers", Hash)
+  end
+
+  def test_valid_api_argument_class_falsey
+    log = with_array_logger do 
+      NewRelic::Agent.manual_start
+      refute valid_api_argument_class?("bogus", "headers", Hash)
+    end
+
+    assert_log_contains(log, /Bad argument passed to #block/)
+    assert_log_contains(log, /Expected Hash for `headers` but got String/)
+  end
+end
Repository: ruby/rbs (Ruby)

Issue:
[Bug] RBS::Parser.parse_signature unable to parse .rbs generated for method with argument forwarding 
```shell
> ruby -v
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]
> rbs -v
rbs 1.0.0
```

Result of `rbs prototype rb` for 
```ruby
class Foo
  def bar(...)
    puts(...)
  end
end
```
is
```rbs
class Foo
  def bar: (*untyped *) { () -> untyped } -> untyped
end
```
Yet `RBS::Parser.parse_signature` unable to parse above rbs and fails with
```shell
parser.y:1419:in `on_error': parse error on value: #<RBS::Parser::LocatedValue:0x00007fee22894820 @location=#<RBS::Location:780 @buffer=, @pos=49...50, source='*', start_line=3, start_column=26>, @value="*"> (kSTAR) (RBS::Parser::SyntaxError)
	from (eval):3:in `_racc_do_parse_c'
	from (eval):3:in `do_parse'
	from parser.y:1124:in `parse_signature'
	from /Users/olegolkhovoy/RubymineProjects/untitled8/fc/cat.rb:5:in `<main>'
```


Discussion:
Thanks for your feedback!


It is a bug of `rbs prototype rb`. The generated RBS is invalid.
RubyVM::AbstractSyntaxTree returns `:*` as an argument name when the `def` use the argument forwarding syntax.
But `*` is not allowed as an argument name in RBS, so it causes a syntax error.



I've fixed this problem on #560.
The `*` argument name will be omitted by this change. 





Patch:
diff --git a/lib/rbs/prototype/rb.rb b/lib/rbs/prototype/rb.rb
index a1d9b0aae..b6464aeb5 100644
--- a/lib/rbs/prototype/rb.rb
+++ b/lib/rbs/prototype/rb.rb
@@ -400,7 +400,8 @@ def function_type_from_body(node)
         end
 
         if rest
-          fun = fun.update(rest_positionals: Types::Function::Param.new(name: rest, type: untyped))
+          rest_name = rest == :* ? nil : rest # # For `def f(...) end` syntax
+          fun = fun.update(rest_positionals: Types::Function::Param.new(name: rest_name, type: untyped))
         end
 
         table_node.drop(fun.required_positionals.size + fun.optional_positionals.size + (fun.rest_positionals ? 1 : 0)).take(post_num).each do |name|
@@ -565,7 +566,10 @@ def block_from_body(node)
 
         if block
           method_block = Types::Block.new(
-            required: true,
+            # HACK: The `block` is :& on `def m(...)` syntax.
+            #       In this case the block looks optional in most cases, so it marks optional.
+            #       In other cases, we can't determine which is required or optional, so it marks required.
+            required: block != :&,
             type: Types::Function.empty(untyped)
           )
         end


Test patch:
diff --git a/test/rbs/rb_prototype_test.rb b/test/rbs/rb_prototype_test.rb
index b978f3acb..8663a844b 100644
--- a/test/rbs/rb_prototype_test.rb
+++ b/test/rbs/rb_prototype_test.rb
@@ -721,4 +721,24 @@ def not_refinements: () -> nil
 end
     RBS
   end
+
+  if RUBY_VERSION >= '2.7'
+    def test_argument_forwarding
+      parser = RB.new
+
+      rb = <<~'RUBY'
+module M
+  def foo(...) end
+end
+      RUBY
+
+      parser.parse(rb)
+
+      assert_write parser.decls, <<~RBS
+module M
+  def foo: (*untyped) ?{ () -> untyped } -> nil
+end
+      RBS
+    end
+  end
 end
Repository: ruby/rbs (Ruby)

Issue:
type of class instance variable
`rbs prototype rb` always generates `untyped` for class instance variables.
And `rbs subtract` does not remove the type of class instance variables.

```console
% rbs --version
rbs 3.8.1
% cat class_instance_variable.rb
class C
  @civ = []
end
% cat sig/class_instance_variable.rbs
class C
  self.@civ: Array
end
% rbs prototype rb class_instance_variable.rb -o prototype
Processing `class_instance_variable.rb`...
  Generating RBS for `class_instance_variable.rb`...
    - Writing RBS to `prototype/class_instance_variable.rbs`...
% cat prototype/class_instance_variable.rbs
class C
  self.@civ: untyped
end
% rbs subtract --write prototype sig
% cat prototype/class_instance_variable.rbs
class C
  self.@civ: untyped
end
```

How can I empty prototype after `rbs subtract` with class instance variables?



Discussion:

Patch:
diff --git a/lib/rbs/subtractor.rb b/lib/rbs/subtractor.rb
index bf4440678..d772505c8 100644
--- a/lib/rbs/subtractor.rb
+++ b/lib/rbs/subtractor.rb
@@ -107,7 +107,9 @@ def call(minuend = @minuend, context: nil)
       each_member(owner).any? do |m|
         case m
         when AST::Members::InstanceVariable
-          m.name == name
+          m.name == name && kind == :instance
+        when AST::Members::ClassInstanceVariable
+          m.name == name && kind == :singleton
         when AST::Members::Attribute
           ivar_name = m.ivar_name == false ? nil : m.ivar_name || :"@#{m.name}"
           ivar_name == name && m.kind == kind


Test patch:
diff --git a/test/rbs/subtractor_test.rb b/test/rbs/subtractor_test.rb
index a534289d7..21100ecf9 100644
--- a/test/rbs/subtractor_test.rb
+++ b/test/rbs/subtractor_test.rb
@@ -472,6 +472,34 @@ class C
     RBS
   end
 
+  def test_civar
+    decls = to_decls(<<~RBS)
+      class C
+        @v1: untyped
+        self.@v1: untyped
+        @v2: untyped
+        self.@v2: untyped
+      end
+    RBS
+
+    env = to_env(<<~RBS)
+      class C
+        self.@v1: untyped
+      end
+    RBS
+
+    subtracted = RBS::Subtractor.new(decls, env).call
+
+    assert_subtracted <<~RBS, subtracted
+      class C
+        @v1: untyped
+
+        @v2: untyped
+        self.@v2: untyped
+      end
+    RBS
+  end
+
   def test_cvar
     decls = to_decls(<<~RBS)
       class C
Repository: basecamp/kamal (Ruby)

Issue:
Bad error when accessory cli is entered wrong
When trying to stop/remove an accessory I incorrectly edited the command and it gave a poor error message.

What I meant to type was `mrsk accessory stop newrelic -d production` and what I actually ran was `mrsk accessory details stop -d production`:

Which is a nonsense command, but it gives:

```bash
$ mrsk accessory details stop -d production
  ERROR (Module::DelegationError): Mrsk::Commands::Accessory#hosts delegated to accessory_config.hosts, but accessory_config is nil: #<Mrsk::Commands::Accessory:0x0000ffff7bd31708 @config=#<Mrsk::Configuration:0x0000ffff7bd3c838 @raw_config=#<ActiveSupport::InheritableOptions {}>, @destination="production", @declared_version=nil, @roles=[#<Mrsk::Configuration::Role:0x0000ffff7bd3c158 @name="web", @config=#<Mrsk::Configuration:0x0000ffff7bd3c838 ...>, @hosts=["170.64.164.114", "170.64.172.8"]>], @accessories=[#<Mrsk::Configuration::Accessory:0x0000ffff7bd314d8 @name="newrelic", @config=#<Mrsk::Configuration:0x0000ffff7bd3c838 ...>, @specifics={"image"=>"newrelic/infrastructure:latest", "roles"=>["web"], "env"=>{"clear"=>{"NRIA_LICENSE_KEY"=>"NOTTHEREALKEY"}}, "options"=>{"network"=>"host", "cap-add"=>"SYS_PTRACE", "privileged"=>true, "pid"=>"host"}, "volumes"=>["/:/host:ro", "/var/run/docker.sock:/var/run/docker.sock"]}>]>, @accessory_config=nil>
```

This is a confusing message because the problem isn't that there isn't a hosts config option, it's that I've used `stop` where the `accessory_name` (in my case `newrelic`) should be.

It would be helpful if it told me that it can't find my accessory `stop`.




Discussion:
Please do explore a PR for this 👍



Patch:
diff --git a/lib/kamal/cli/accessory.rb b/lib/kamal/cli/accessory.rb
index e6bce05fb..64cd97cdd 100644
--- a/lib/kamal/cli/accessory.rb
+++ b/lib/kamal/cli/accessory.rb
@@ -226,7 +226,8 @@ def remove_service_directory(name)
 
   private
     def with_accessory(name)
-      if accessory = KAMAL.accessory(name)
+      if KAMAL.config.accessory(name)
+        accessory = KAMAL.accessory(name)
         yield accessory, accessory_hosts(accessory)
       else
         error_on_missing_accessory(name)


Test patch:
diff --git a/test/cli/accessory_test.rb b/test/cli/accessory_test.rb
index f6e6045b9..444b40d2b 100644
--- a/test/cli/accessory_test.rb
+++ b/test/cli/accessory_test.rb
@@ -79,6 +79,10 @@ class CliAccessoryTest < CliTestCase
     assert_match "docker ps --filter label=service=app-mysql", run_command("details", "mysql")
   end
 
+  test "details with non-existent accessory" do
+    assert_equal "No accessory by the name of 'hello' (options: mysql and redis)", stderred { run_command("details", "hello") }
+  end
+
   test "details with all" do
     run_command("details", "all").tap do |output|
       assert_match "docker ps --filter label=service=app-mysql", output
Repository: rack/rack-contrib (Ruby)

Issue:
Add a default response to Rack::NotFound if no 404 file specified
Currently Rack::NotFound requires that a path to a file be provided, that will be served as the custom 404 page:
https://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/not_found.rb

However for some apps a custom 404 page is overkill, so it would be great if Rack::NotFound could provide a default response, to avoid the standard boilerplate seen on so many Stack Overflow posts (most of which also omit the `Content-Length`, against the recommendation of the spec):

ie this:

``` ruby
use Rack::Static,
  ...
  ...

body = "Not found\n"
headers = {"Content-Type" => "text/html", "Content-Length" => body.size.to_s}
run lambda { |_| [404, headers, [body]] }
```

Would become:

``` ruby
use Rack::Static,
  ...
  ...

run Rack::NotFound.new
```

Does this sound like something that would be accepted? :-)



Discussion:
Yes, that does sound like it would be useful.




Patch:
diff --git a/lib/rack/contrib/not_found.rb b/lib/rack/contrib/not_found.rb
index cd0ca8f3..392201fc 100644
--- a/lib/rack/contrib/not_found.rb
+++ b/lib/rack/contrib/not_found.rb
@@ -1,13 +1,25 @@
 module Rack
-  # Rack::NotFound is a default endpoint. Initialize with the path to
-  # your 404 page.
+  # Rack::NotFound is a default endpoint. Optionally initialize with the
+  # path to a custom 404 page, to override the standard response body.
+  #
+  # Examples:
+  #
+  # Serve default 404 response:
+  #   run Rack::NotFound.new
+  #
+  # Serve a custom 404 page:
+  #   run Rack::NotFound.new('path/to/your/404.html')
 
   class NotFound
     F = ::File
 
-    def initialize(path)
-      file = F.expand_path(path)
-      @content = F.read(file)
+    def initialize(path = '')
+      if path.empty?
+        @content = "Not found\n"
+      else
+        file = F.expand_path(path)
+        @content = F.read(file)
+      end
       @length = @content.size.to_s
     end
 


Test patch:
diff --git a/test/404.html b/test/404.html
index 85373076..64c6e832 100644
--- a/test/404.html
+++ b/test/404.html
@@ -1,1 +1,1 @@
-Not Found
\ No newline at end of file
+Custom 404 page content
\ No newline at end of file
diff --git a/test/spec_rack_not_found.rb b/test/spec_rack_not_found.rb
index 19729059..8b5b0537 100644
--- a/test/spec_rack_not_found.rb
+++ b/test/spec_rack_not_found.rb
@@ -10,7 +10,19 @@
       run Rack::NotFound.new('test/404.html')
     end
     response = Rack::MockRequest.new(app).get('/')
-    response.body.must_equal('Not Found')
+    response.body.must_equal('Custom 404 page content')
+    response.headers['Content-Length'].must_equal('23')
+    response.status.must_equal(404)
+  end
+
+  specify "should render the default response body if no path specified" do
+    app = Rack::Builder.new do
+      use Rack::Lint
+      run Rack::NotFound.new
+    end
+    response = Rack::MockRequest.new(app).get('/')
+    response.body.must_equal("Not found\n")
+    response.headers['Content-Length'].must_equal('10')
     response.status.must_equal(404)
   end
Repository: fakefs/fakefs (Ruby)

Issue:
mkdir_p '/' creates time bombs
Doing `FileUtils.mkdir_p '/'` places an entry into the file system's root directory that has `@name == nil`. This blows up eventually, since `@name` is expected to always be set. For example, consequent calls to `Dir.children('/')` will fail with `no implicit conversion from nil to String`.

I think a simple guard against this case should be enough to resolve this issue.


Discussion:
thx, 3.0.3



Patch:
diff --git a/lib/fakefs/file_system.rb b/lib/fakefs/file_system.rb
index a699635..f502d51 100644
--- a/lib/fakefs/file_system.rb
+++ b/lib/fakefs/file_system.rb
@@ -56,6 +56,9 @@ def add(path, object = FakeDir.new)
       end
 
       assert_dir d
+      # Short-circuit if added path is file system root, to avoid adding nil-name fs entries:
+      return fs if parts.empty?
+
       object.name = parts.last
       object.parent = d
       if object.is_a? FakeDir


Test patch:
diff --git a/test/fakefs_test.rb b/test/fakefs_test.rb
index bc12f45..25831d2 100644
--- a/test/fakefs_test.rb
+++ b/test/fakefs_test.rb
@@ -3253,6 +3253,11 @@ def test_mkdir_raises_error_if_already_created
     end
   end
 
+  def test_mkdir_p_of_root_does_not_cause_faulty_entries
+    FileUtils.mkdir_p '/'
+    refute_includes FakeFS::FileSystem.fs.entries.map(&:name), nil
+  end
+
   def test_directory_open
     test = ['.', '..', 'file_1', 'file_2', 'file_3', 'file_4', 'file_5']
Repository: heapsource/active_model_otp (Ruby)

Issue:
Token with empty string return true on authenticate_otp
I authenticate the token filled in by the user like this, where `params[:otp_token]` is the user filled token from the view:
```
result = current_user.authenticate_otp(params[:otp_token], drift: 300)
```
I noticed when `params[:otp_token]` is an empty string, that the result is `true`, which should be `false`?
In my opinion any empty or nil value should always result in a `false` result?


Discussion:
Hello, @jarkelen ! 👋 

Thanks for your report.

I've opened a pull request with that bugfix, can you test inside your application? I believe that will be fixed now.

To test, please make something like this in your Gemfile:

```ruby
gem 'active_model_otp', github: 'heapsource/active_model_otp', branch: 'master'
```
Sorry for my late reaction, it works, thanks!



Patch:
diff --git a/lib/active_model/one_time_password.rb b/lib/active_model/one_time_password.rb
index 107fa16..395b59a 100644
--- a/lib/active_model/one_time_password.rb
+++ b/lib/active_model/one_time_password.rb
@@ -72,6 +72,7 @@ def otp_regenerate_counter
       end
 
       def authenticate_otp(code, options = {})
+        return false if code.nil? || code.empty?
         return true if backup_codes_enabled? && authenticate_backup_code(code)
 
         if otp_counter_based


Test patch:
diff --git a/test/one_time_password_test.rb b/test/one_time_password_test.rb
index c26b8ba..ec4d58c 100644
--- a/test/one_time_password_test.rb
+++ b/test/one_time_password_test.rb
@@ -33,6 +33,23 @@ def test_authenticate_with_otp
     assert @visitor.authenticate_otp(code)
   end
 
+  def test_authenticate_with_otp_passing_false_or_empty_codes
+    refute @user.authenticate_otp(nil)
+    refute @user.authenticate_otp('')
+
+    refute @visitor.authenticate_otp(nil)
+    refute @visitor.authenticate_otp('')
+
+    refute @member.authenticate_otp(nil)
+    refute @member.authenticate_otp('')
+
+    refute @ar_user.authenticate_otp(nil)
+    refute @ar_user.authenticate_otp('')
+
+    refute @opt_in.authenticate_otp(nil)
+    refute @opt_in.authenticate_otp('')
+  end
+
   def test_counter_based_otp
     code = @member.otp_code
     assert @member.authenticate_otp(code)
Repository: tweag/topiary (Rust)

Issue:
Clean up trailing spaces after formatting
When the pretty crate indents a block of code, it will also turn a blank line into a sequence of spaces. We need to trim these away.


Discussion:

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 2fd3c8aa..4a38db2e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -107,6 +107,12 @@ version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
 
+[[package]]
+name = "either"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
+
 [[package]]
 name = "env_logger"
 version = "0.9.0"
@@ -157,6 +163,15 @@ dependencies = [
  "hashbrown",
 ]
 
+[[package]]
+name = "itertools"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
+dependencies = [
+ "either",
+]
+
 [[package]]
 name = "libc"
 version = "0.2.132"
@@ -341,6 +356,7 @@ version = "0.1.0"
 dependencies = [
  "clap",
  "env_logger",
+ "itertools",
  "log",
  "pretty",
  "pretty_assertions",
diff --git a/Cargo.toml b/Cargo.toml
index f75b777a..87980451 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,6 +9,7 @@ edition = "2021"
 # Eventually we will want to dynamically load them, like Helix does.
 clap = { version = "3.2.17", features = ["derive"]}
 env_logger = "0.9.0"
+itertools = "0.10.3"
 log = "0.4.17"
 pretty = "0.11"
 test-log = "0.2.11"
diff --git a/src/lib.rs b/src/lib.rs
index 5fa7550d..c28d27d1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,5 @@
 use clap::ArgEnum;
+use itertools::Itertools;
 use pretty::RcDoc;
 use std::collections::BTreeSet;
 use std::collections::HashSet;
@@ -84,7 +85,14 @@ pub fn formatter(
 
     // Convert our list of atoms to a Doc
     let doc = atoms_to_doc(&mut 0, &atoms);
-    doc.render(200, output)?;
+    let mut rendered = String::new();
+    doc.render_fmt(usize::max_value(), &mut rendered)?;
+
+    // Remove trailing spaces from lines
+    let trimmed: String =
+        Itertools::intersperse(rendered.split('\n').map(|line| line.trim_end()), "\n").collect();
+
+    write!(output, "{trimmed}")?;
 
     Ok(())
 }


Test patch:
diff --git a/tests/samples/expected/rust.rs b/tests/samples/expected/rust.rs
index d667c0ed..3190107a 100644
--- a/tests/samples/expected/rust.rs
+++ b/tests/samples/expected/rust.rs
@@ -19,16 +19,16 @@ enum NoFinalComma {
 }
 
 enum ExpandTwoLevels {
-  
+
   Leaf {
     content: String, //   Comment after field declaration in enum variant.
     id: usize,
-    
+
     size: usize,
   },
   Hardline { content: String, id: usize },
-   
+
   // comment between enum items
-  
+
   Space,
 }
Repository: tokio-rs/async-stream (Rust)

Issue:
`try_stream! {foo?}` doesn't convert Error types like regular `foo?`
Given
```rust
struct ErrorA(u8);
struct ErrorB(u8);
impl From<ErrorA> for ErrorB {
    fn from(a: ErrorA) -> ErrorB {
        ErrorB(a.0)
    }
}
```

"Normal" (synchronous Rust) will convert error types:
```rust
fn sync() -> Result<&'static str, ErrorB> {
        if true {
            Err(ErrorA(1))?;
        } else {
            Err(ErrorB(2))?;
        }
        Ok("unreachable")
}
```

But `try_stream!` does not:
```rust
fn async() -> impl Stream<Item = Result<&'static str, ErrorB>>
    try_stream! {
            if true {
                Err(ErrorA(1))?;
            } else {
                Err(ErrorB(2))?;
            }
            yield "unreachable";
    }
}
```
Gives (some variation of):
```
   = note: expected type `ErrorA`
              found type `ErrorB`
```


Discussion:
Thanks for this!



Patch:
diff --git a/async-stream-impl/src/lib.rs b/async-stream-impl/src/lib.rs
index daf1bb0..8039444 100644
--- a/async-stream-impl/src/lib.rs
+++ b/async-stream-impl/src/lib.rs
@@ -89,7 +89,7 @@ impl VisitMut for Scrub {
                     match #e {
                         Ok(v) => v,
                         Err(e) => {
-                            __yield_tx.send(Err(e)).await;
+                            __yield_tx.send(Err(e.into())).await;
                             return;
                         }
                     }


Test patch:
diff --git a/async-stream/tests/try_stream.rs b/async-stream/tests/try_stream.rs
index 7748ffc..a387e8f 100644
--- a/async-stream/tests/try_stream.rs
+++ b/async-stream/tests/try_stream.rs
@@ -32,3 +32,30 @@ async fn yield_then_err() {
     assert_eq!(Ok("hello"), values[0]);
     assert_eq!(Err("world"), values[1]);
 }
+
+#[tokio::test]
+async fn convert_err() {
+    struct ErrorA(u8);
+    #[derive(PartialEq, Debug)]
+    struct ErrorB(u8);
+    impl From<ErrorA> for ErrorB {
+        fn from(a: ErrorA) -> ErrorB {
+            ErrorB(a.0)
+        }
+    }
+
+    fn test() -> impl Stream<Item = Result<&'static str, ErrorB>> {
+        try_stream! {
+            if true {
+                Err(ErrorA(1))?;
+            } else {
+                Err(ErrorB(2))?;
+            }
+            yield "unreachable";
+        }
+    }
+
+    let values: Vec<_> = test().collect().await;
+    assert_eq!(1, values.len());
+    assert_eq!(Err(ErrorB(1)), values[0]);
+}
Repository: 0xMiden/miden-vm (Rust)

Issue:
Advice Map bug in test-utils
When testing a script with an advice map using the test-utils framework, even if the map is correctly loaded by the host, the event handler is unable to find the key because the map is empty.
See `processor/src/tests.rs::test_advice_map_inline`.

There is a trait with several implementations, some just for testing so there is probably a bug in one of them or in the way they are linked.

The same script can be successfully tested using the cli where the advice map is correctly populated and queried, see `miden-vm/tests/integration/cli/cli_test.rs::test_advmap_cli`.


Discussion:

Patch:
diff --git a/processor/src/fast/mod.rs b/processor/src/fast/mod.rs
index b31fd51f5a..8e0880b2bd 100644
--- a/processor/src/fast/mod.rs
+++ b/processor/src/fast/mod.rs
@@ -359,6 +359,11 @@ impl FastProcessor {
         let mut continuation_stack = ContinuationStack::new(program);
         let mut current_forest = program.mast_forest().clone();
 
+        // Merge the program's advice map into the advice provider
+        self.advice
+            .extend_map(current_forest.advice_map())
+            .map_err(|err| ExecutionError::advice_error(err, self.clk, &()))?;
+
         while let Some(continuation) = continuation_stack.pop_continuation() {
             match continuation {
                 Continuation::StartNode(node_id) => {


Test patch:
diff --git a/processor/src/tests.rs b/processor/src/tests.rs
index dcf6608dd3..81b20e0749 100644
--- a/processor/src/tests.rs
+++ b/processor/src/tests.rs
@@ -21,19 +21,18 @@ use super::*;
 // AdviceMap inlined in the script
 // ------------------------------------------------------------------------------------------------
 
-#[ignore] // tracked by https://github.com/0xMiden/miden-vm/issues/1886
 #[test]
 fn test_advice_map_inline() {
     let source = "\
-adv_map.A=2
+adv_map.A=[0x01]
 
 begin
   push.A
   adv.push_mapval
+  dropw
   adv_push.1
-  push.2
+  push.1
   assert_eq
-  dropw
 end";
 
     let build_test = build_test!(source);
Repository: dtolnay/proc-macro2 (Rust)

Issue:
Issue with multibyte chars in source_text() computation
It treats `lo` as a byte index, while it is actually a character index:

https://github.com/dtolnay/proc-macro2/blob/7f5533d6cc9ff783d174aec4e3be2caa202b62ca/src/fallback.rs#L367

I expect this test to pass, but it does not:

```rust
#[cfg(span_locations)]
#[test]
fn source_text() {
    let input = "    𓀕 c    ";
    let mut tokens = input
        .parse::<proc_macro2::TokenStream>()
        .unwrap()
        .into_iter();

    let ident1 = tokens.next().unwrap();
    assert_eq!("𓀕", ident1.span().source_text().unwrap());

    let ident2 = tokens.next().unwrap();
    assert_eq!("𓀕", ident2.span().source_text().unwrap());
}
```

Panics with (as character `𓀕` occupies byte 5 and 6)
```
---- source_text stdout ----
thread 'source_text' panicked at 'byte index 6 is not a char boundary; it is inside '𓀕' (bytes 4..8) of `    𓀕 c   `', src/fallback.rs:367:25
```


Discussion:
I have published a fix in proc-macro2 1.0.69.



Patch:
diff --git a/src/fallback.rs b/src/fallback.rs
index 281b7b2..70deb4b 100644
--- a/src/fallback.rs
+++ b/src/fallback.rs
@@ -364,7 +364,10 @@ impl FileInfo {
 
     fn source_text(&self, span: Span) -> String {
         let lo = (span.lo - self.span.lo) as usize;
-        let trunc_lo = &self.source_text[lo..];
+        let trunc_lo = match self.source_text.char_indices().nth(lo) {
+            Some((offset, _ch)) => &self.source_text[offset..],
+            None => return String::new(),
+        };
         let char_len = (span.hi - span.lo) as usize;
         let source_text = match trunc_lo.char_indices().nth(char_len) {
             Some((offset, _ch)) => &trunc_lo[..offset],


Test patch:
diff --git a/tests/test.rs b/tests/test.rs
index 4a6ca75..1916a85 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -328,10 +328,17 @@ fn literal_span() {
 #[cfg(span_locations)]
 #[test]
 fn source_text() {
-    let input = "    𓀕    ";
-    let tokens = input.parse::<proc_macro2::TokenStream>().unwrap();
-    let ident = tokens.into_iter().next().unwrap();
+    let input = "    𓀕 c    ";
+    let mut tokens = input
+        .parse::<proc_macro2::TokenStream>()
+        .unwrap()
+        .into_iter();
+
+    let ident = tokens.next().unwrap();
     assert_eq!("𓀕", ident.span().source_text().unwrap());
+
+    let ident = tokens.next().unwrap();
+    assert_eq!("c", ident.span().source_text().unwrap());
 }
 
 #[test]
Repository: chatmail/core (Rust)

Issue:
saved messages not always marked with a padlock
when creating a **new** chatmail account, and typing a new message to "saved messages" (so, not forwarding or so), the message is _not_ marked as being end-to-end encrypted (so, no padlock)

once a backup is exported for that account, typed messages are marked as being end-to-end encrypted

i assume this is related to recent changes wrt bcc-self - so the initially sent messages are probable never sent over the wire.

while this may be technically correct, it is pretty confusing, esp. as the "saved messages" is marked with a green checkmark (also recently)

also, it affects new users  - after setup a new chatmail account, there are only these two chats, would be better if sending something there does not directly result in questions :)


Discussion:

Patch:
diff --git a/src/chat.rs b/src/chat.rs
index 7f3bbf8867..428b2ad2b9 100644
--- a/src/chat.rs
+++ b/src/chat.rs
@@ -3024,6 +3024,8 @@ pub(crate) async fn create_send_msg_jobs(context: &Context, msg: &mut Message) -
             context,
             "Message {} has no recipient, skipping smtp-send.", msg.id
         );
+        msg.param.set_int(Param::GuaranteeE2ee, 1);
+        msg.update_param(context).await?;
         msg.id.set_delivered(context).await?;
         msg.state = MessageState::OutDelivered;
         return Ok(Vec::new());


Test patch:
diff --git a/src/chat/chat_tests.rs b/src/chat/chat_tests.rs
index cdf81c1f58..f252ae1c81 100644
--- a/src/chat/chat_tests.rs
+++ b/src/chat/chat_tests.rs
@@ -774,6 +774,21 @@ async fn test_self_talk() -> Result<()> {
     Ok(())
 }
 
+/// Tests that when BCC-self is disabled
+/// and no messages are actually sent
+/// in a self-chat, they have a padlock.
+#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
+async fn test_self_talk_no_bcc_padlock() -> Result<()> {
+    let t = &TestContext::new_alice().await;
+    t.set_config_bool(Config::BccSelf, false).await?;
+    let chat = &t.get_self_chat().await;
+
+    let msg_id = send_text_msg(t, chat.id, "Foobar".to_string()).await?;
+    let msg = Message::load_from_db(t, msg_id).await?;
+    assert!(msg.get_showpadlock());
+    Ok(())
+}
+
 #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
 async fn test_add_device_msg_unlabelled() {
     let t = TestContext::new().await;
Repository: veryl-lang/veryl (Rust)

Issue:
Can't refer member variables via generirc parameter
Veryl reports `invisible_identifier` error for member references via generic parameters.

```systemverilog
    if INFO.width >: 0 {
      packer_next[INFO.pos+:INFO.width] = value;
    }
```

![Image](https://github.com/user-attachments/assets/8356b5e7-c144-4dab-9a04-8d25271f8dad)


Discussion:

Patch:
diff --git a/crates/analyzer/src/symbol_table.rs b/crates/analyzer/src/symbol_table.rs
index c634f5902..6eedf1fa6 100644
--- a/crates/analyzer/src/symbol_table.rs
+++ b/crates/analyzer/src/symbol_table.rs
@@ -425,6 +425,7 @@ impl SymbolTable {
                     | SymbolKind::ProtoConst(_)
                     | SymbolKind::StructMember(_)
                     | SymbolKind::UnionMember(_)
+                    | SymbolKind::GenericParameter(_)
             ),
             SymbolKind::Parameter(_)
             | SymbolKind::ProtoConst(_)


Test patch:
diff --git a/crates/analyzer/src/tests.rs b/crates/analyzer/src/tests.rs
index 9dcf2c492..a5a80c9e5 100644
--- a/crates/analyzer/src/tests.rs
+++ b/crates/analyzer/src/tests.rs
@@ -3591,6 +3591,22 @@ fn invisible_identifier() {
 
     let errors = analyze(code);
     assert!(errors.is_empty());
+
+    let code = r#"
+    module ModuleA {
+        struct Foo {
+            foo: logic,
+        }
+        function Func::<foo: Foo>() -> logic {
+            return foo.foo;
+        }
+        const FOO: Foo = Foo'{ foo: 0 };
+        let _foo: logic = Func::<FOO>();
+    }
+    "#;
+
+    let errors = analyze(code);
+    assert!(errors.is_empty());
 }
 
 #[test]
Repository: veryl-lang/veryl (Rust)

Issue:
Not detect `generic arity mismtach` error for generic interface used as modport
Veryl compiler panics during analyzing the code below but not not report `generic arity mismtach` error.

```systemverilog
interface a_if::<W: u32> {
    var a: logic<W>;
    modport mp {
        a: input
    }
}
module b_module (
    aif: modport a_if::mp,
){}
```


Discussion:

Patch:
diff --git a/crates/analyzer/src/symbol.rs b/crates/analyzer/src/symbol.rs
index a5b52e7ef..efb6ed47d 100644
--- a/crates/analyzer/src/symbol.rs
+++ b/crates/analyzer/src/symbol.rs
@@ -390,16 +390,28 @@ impl Symbol {
     }
 
     pub fn generic_table(&self, arguments: &[GenericSymbolPath]) -> GenericTable {
-        let generic_parameters = self.generic_parameters();
+        let params = self.generic_parameters();
+        let n_args = arguments.len();
         let mut ret = HashMap::default();
 
+        let match_arity = if params.len() > n_args {
+            params[n_args].1.default_value.is_some()
+        } else {
+            params.len() == n_args
+        };
+        if !match_arity {
+            // Too many or too few generic args are given.
+            // Return empty generic table.
+            return ret;
+        }
+
         for (i, arg) in arguments.iter().enumerate() {
-            if let Some((p, _)) = generic_parameters.get(i) {
+            if let Some((p, _)) = params.get(i) {
                 ret.insert(*p, arg.clone());
             }
         }
 
-        for param in generic_parameters.iter().skip(arguments.len()) {
+        for param in params.iter().skip(n_args) {
             ret.insert(param.0, param.1.default_value.as_ref().unwrap().clone());
         }
 


Test patch:
diff --git a/crates/analyzer/src/tests.rs b/crates/analyzer/src/tests.rs
index 1e70b260c..08879f1ee 100644
--- a/crates/analyzer/src/tests.rs
+++ b/crates/analyzer/src/tests.rs
@@ -1378,6 +1378,24 @@ fn mismatch_generics_arity() {
 
     let errors = analyze(code);
     assert!(errors.is_empty());
+
+    let code = r#"
+    interface a_if::<W: u32> {
+        var a: logic<W>;
+        modport mp {
+            a: input
+        }
+    }
+    module b_module (
+        aif: modport a_if::mp,
+    ){}
+    "#;
+
+    let errors = analyze(code);
+    assert!(matches!(
+        errors[0],
+        AnalyzerError::MismatchGenericsArity { .. }
+    ));
 }
 
 #[test]
Repository: veryl-lang/veryl (Rust)

Issue:
Can't refer struct member via proto const
Veryl compiler reports `unknown_member` for the following code.

```systemverilog
package PkgA {
  struct Foo {
    foo: logic,
  }
}

proto package ProtoPkgB {
  const FOO: PkgA::Foo;
}

package PkgB for ProtoPkgB {
  const FOO: PkgA::Foo = PkgA::Foo'{foo: 0};
}

module ModuleA::<PKG: ProtoPkgB> {
  let _foo: logic = PKG::FOO.foo;
}

module ModuleB {
  inst u: ModuleA::<PkgB>;
}
```

![Image](https://github.com/user-attachments/assets/2c120fd3-3f8b-4550-9fff-05e128668d91)


Discussion:

Patch:
diff --git a/crates/analyzer/src/symbol_table.rs b/crates/analyzer/src/symbol_table.rs
index 6eedf1fa6..4e79bb069 100644
--- a/crates/analyzer/src/symbol_table.rs
+++ b/crates/analyzer/src/symbol_table.rs
@@ -570,6 +570,9 @@ impl SymbolTable {
                                     context = self.trace_type_kind(context, &x.r#type.kind)?;
                                 }
                             }
+                            SymbolKind::ProtoConst(x) => {
+                                context = self.trace_type_kind(context, &x.r#type.kind)?;
+                            }
                             SymbolKind::TypeDef(x) => {
                                 context = self.trace_type_kind(context, &x.r#type.kind)?;
                             }
@@ -628,7 +631,6 @@ impl SymbolTable {
                             | SymbolKind::ProtoModule(_)
                             | SymbolKind::Struct(_)
                             | SymbolKind::Union(_)
-                            | SymbolKind::ProtoConst(_)
                             | SymbolKind::ProtoTypeDef
                             | SymbolKind::Modport(_)
                             | SymbolKind::ModportFunctionMember(_)


Test patch:
diff --git a/crates/analyzer/src/tests.rs b/crates/analyzer/src/tests.rs
index 7ba5b8be4..8bc91b46d 100644
--- a/crates/analyzer/src/tests.rs
+++ b/crates/analyzer/src/tests.rs
@@ -4053,6 +4053,23 @@ fn unknown_member() {
 
     let errors = analyze(code);
     assert!(errors.is_empty());
+
+    let code = r#"
+    package PkgA {
+        struct Foo {
+            foo: logic,
+        }
+    }
+    proto package ProtoPkgB {
+        const FOO: PkgA::Foo;
+    }
+    module ModuleA::<PKG: ProtoPkgB> {
+        let _foo: logic = PKG::FOO.foo;
+    }
+    "#;
+
+    let errors = analyze(code);
+    assert!(errors.is_empty());
 }
 
 #[test]
Repository: dtolnay/proc-macro2 (Rust)

Issue:
Op followed by comment should not be considered joint
```rust
for tt in "~// comment".parse::<TokenStream>().unwrap() {
    println!("{:?}", tt);
}
```

Proc-macro:

```
Op(Op { op: '~', spacing: Alone, span: Span(...) })
```

Proc-macro2:

```
Op(Op { op: '~', spacing: Joint, span: Span })
```

The comment should be considered whitespace, making the preceding op alone rather than joint.


Discussion:
Still incorrect as of proc-macro2 0.3.5.



Patch:
diff --git a/src/stable.rs b/src/stable.rs
index ad9870ce..7bcdaad9 100644
--- a/src/stable.rs
+++ b/src/stable.rs
@@ -1198,6 +1198,11 @@ fn op(input: Cursor) -> PResult<Op> {
 }
 
 fn op_char(input: Cursor) -> PResult<char> {
+    if input.starts_with("//") || input.starts_with("/*") {
+        // Do not accept `/` of a comment as an op.
+        return Err(LexError);
+    }
+
     let mut chars = input.chars();
     let first = match chars.next() {
         Some(ch) => ch,


Test patch:
diff --git a/tests/test.rs b/tests/test.rs
index caed47ce..5ed21a4f 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -2,7 +2,7 @@ extern crate proc_macro2;
 
 use std::str::{self, FromStr};
 
-use proc_macro2::{Literal, Span, Term, TokenStream, TokenTree};
+use proc_macro2::{Literal, Spacing, Span, Term, TokenStream, TokenTree};
 
 #[test]
 fn terms() {
@@ -293,6 +293,18 @@ fn tricky_doc_comment() {
     assert!(tokens.len() == 3, "not length 3 -- {:?}", tokens);
 }
 
+#[test]
+fn op_before_comment() {
+    let mut tts = TokenStream::from_str("~// comment").unwrap().into_iter();
+    match tts.next().unwrap() {
+        TokenTree::Op(tt) => {
+            assert_eq!(tt.op(), '~');
+            assert_eq!(tt.spacing(), Spacing::Alone);
+        }
+        wrong => panic!("wrong token {:?}", wrong),
+    }
+}
+
 #[test]
 fn raw_identifier() {
     let mut tts = TokenStream::from_str("r#dyn").unwrap().into_iter();