Repository: tailwindlabs/tailwindcss (TypeScript)

Issue:
When defining dash-prefixed utility classes in a @layer, using them in an @apply statement throws a build error
<!-- Please provide all of the information requested below. We're a small team and without all of this information it's not possible for us to help and your bug report will be closed. -->

**What version of Tailwind CSS are you using?**

Tailwind v3.1.7

**What build tool (or framework if it abstracts the build tool) are you using?**

Tailwindcss CLI tool

**What version of Node.js are you using?**

Node v16.6.2

**What browser are you using?**

N/A, CLI issue

**What operating system are you using?**

macOS

**Reproduction URL**

Repo with basic demo code: https://github.com/lform/tailwind-dash-demo

**Describe your issue**

We're creating some utility classes in a `@layer utilities` layer that extend each other using `@apply` statements to create a simple header font-sizing system that utilizes modular scale. 

The classes work fine except if you try to use a dash-prefixed class thats been defined in the utilites layer in one of the `@apply` statements. There are workarounds but they would break the consistency of using the dash-prefix for negative values that tailwind employs uniformly. We're building out some re-usable components and want to utilize those font-sizing classes in them so this is a bit of a hindrence. We've temporarily changed the syntax to `h-ms--1` to work around this but its not ideal as it doesnt obey the consistency.

The above repo has the full code demo but basically the following is the problem:

```
@layer utilities {
	.h-ms {
		/* Works fine */
		@apply font-header leading-tight;
	}

	.h-ms-1 {
		/* Works fine */
		@apply h-ms text-ms-1 font-bold;
	}

	.-h-ms-1 {
		/* Works fine, `-text-ms-1` is defined in the tailwind config */
		@apply h-ms -text-ms-1 font-bold;
	}

	.new-class {
		/* This throws the below error */
		@apply -h-ms-1 italic;
	}
}
```

Which then throws the following error (the error goes away if you remove the offending dash-prefixed item in question from the apply statement):
```
TypeError: Cannot read property 'parent' of undefined
    at Root.normalize (/Users/bmf/sites/tailwind-dash-test/node_modules/postcss/lib/container.js:292:15)
    at Root.normalize (/Users/bmf/sites/tailwind-dash-test/node_modules/postcss/lib/root.js:25:23)
    at Root.insertAfter (/Users/bmf/sites/tailwind-dash-test/node_modules/postcss/lib/container.js:201:22)
    at Rule.after (/Users/bmf/sites/tailwind-dash-test/node_modules/postcss/lib/node.js:161:17)
    at processApply (/Users/bmf/sites/tailwind-dash-test/node_modules/tailwindcss/lib/lib/expandApplyAtRules.js:453:16)
    at /Users/bmf/sites/tailwind-dash-test/node_modules/tailwindcss/lib/lib/expandApplyAtRules.js:471:9
    at /Users/bmf/sites/tailwind-dash-test/node_modules/tailwindcss/lib/processTailwindFeatures.js:55:50
    at Object.Once (/Users/bmf/sites/tailwind-dash-test/node_modules/tailwindcss/lib/cli.js:682:27)
    at LazyResult.runOnRoot (/Users/bmf/sites/tailwind-dash-test/node_modules/postcss/lib/lazy-result.js:337:23)
    at LazyResult.runAsync (/Users/bmf/sites/tailwind-dash-test/node_modules/postcss/lib/lazy-result.js:393:26)
```

Is there another way to approach this that would work? Not sure if this is a bug, expected or the wrong way to create these utility classes. Open to suggestions if there's a more correct approach, was unable to find any help when searching this issue online.


Hints:

Patch:
diff --git a/src/lib/expandApplyAtRules.js b/src/lib/expandApplyAtRules.js
--- a/src/lib/expandApplyAtRules.js
+++ b/src/lib/expandApplyAtRules.js
@@ -499,6 +499,12 @@ function processApply(root, context, localCache) {
           })
         }
 
+        // It could be that the node we were inserted was removed because the class didn't match
+        // If that was the *only* rule in the parent, then we have nothing add so we skip it
+        if (!root.nodes[0]) {
+          continue
+        }
+
         // Insert it
         siblings.push([
           // Ensure that when we are sorting, that we take the layer order into account


Test patch:
diff --git a/tests/apply.test.js b/tests/apply.test.js
--- a/tests/apply.test.js
+++ b/tests/apply.test.js
@@ -1548,3 +1548,39 @@ it('apply + user CSS + selector variants (like group) + important selector (2)',
     }
   `)
 })
+
+it('can apply user utilities that start with a dash', async () => {
+  let config = {
+    content: [{ raw: html`<div class="foo-1 -foo-1 new-class"></div>` }],
+    plugins: [],
+  }
+
+  let input = css`
+    @tailwind utilities;
+    @layer utilities {
+      .foo-1 {
+        margin: 10px;
+      }
+      .-foo-1 {
+        margin: -15px;
+      }
+      .new-class {
+        @apply -foo-1;
+      }
+    }
+  `
+
+  let result = await run(input, config)
+
+  expect(result.css).toMatchFormattedCss(css`
+    .foo-1 {
+      margin: 10px;
+    }
+    .-foo-1 {
+      margin: -15px;
+    }
+    .new-class {
+      margin: -15px;
+    }
+  `)
+})