diff --git a/macros/src/check.rs b/macros/src/check.rs
index e4a716bcd18d91973ad25d41b99d3f9f68857561..42dd3c9ecad4f3c097734004136f9dc3d75cb1bb 100644
--- a/macros/src/check.rs
+++ b/macros/src/check.rs
@@ -49,7 +49,7 @@ pub enum Kind {
 
 pub struct Task {
     pub kind: Kind,
-    pub path: Option<Path>,
+    pub path: Path,
     pub priority: u8,
     pub resources: Idents,
 }
@@ -122,7 +122,7 @@ fn task(name: &str, task: syntax::check::Task) -> Result<Task> {
 
     Ok(Task {
         kind,
-        path: task.path,
+        path: task.path.ok_or("`path` field is missing")?,
         priority: task.priority.unwrap_or(1),
         resources: task.resources,
     })
diff --git a/macros/src/trans.rs b/macros/src/trans.rs
index 02b5e8cdb02ed5f6e4656745cfd9c7fdc11d358a..a6dcf8abed5644e6ee930dfe464aebf3b48365cd 100644
--- a/macros/src/trans.rs
+++ b/macros/src/trans.rs
@@ -603,67 +603,41 @@ fn tasks(app: &App, ownerships: &Ownerships, root: &mut Vec<Tokens>) {
             });
         }
 
-        if let Some(path) = task.path.as_ref() {
-            let mut tys = vec![];
-            let mut exprs = vec![];
-
-            let priority = task.priority;
-            if needs_threshold {
-                tys.push(quote!(&mut #krate::Threshold));
-                exprs.push(quote! {
-                    &mut if #priority == 1 << #device::NVIC_PRIO_BITS {
-                        #krate::Threshold::new(::core::u8::MAX)
-                    } else {
-                        #krate::Threshold::new(#priority)
-                    }
-                });
-            }
-
-            if has_resources {
-                tys.push(quote!(#name::Resources));
-                exprs.push(quote!(#name::Resources::new()));
-            }
-
-            let _name = Ident::new(format!("_{}", name));
-            let export_name =
-                Lit::Str(name.as_ref().to_owned(), StrStyle::Cooked);
-            root.push(quote! {
-                #[allow(non_snake_case)]
-                #[allow(unsafe_code)]
-                #[export_name = #export_name]
-                pub unsafe extern "C" fn #_name() {
-                    let f: fn(#(#tys,)*) = #path;
-
-                    f(#(#exprs,)*)
-                }
-            });
-        } else if !has_resources {
-            items.push(quote! {
-                pub struct Resources {
-                    _0: (),
-                }
+        let mut tys = vec![];
+        let mut exprs = vec![];
 
-                impl Resources {
-                    pub unsafe fn new() -> Self {
-                        Resources { _0: () }
-                    }
+        let priority = task.priority;
+        if needs_threshold {
+            tys.push(quote!(&mut #krate::Threshold));
+            exprs.push(quote! {
+                &mut if #priority == 1 << #device::NVIC_PRIO_BITS {
+                    #krate::Threshold::new(::core::u8::MAX)
+                } else {
+                    #krate::Threshold::new(#priority)
                 }
             });
-            // the `task!` macro will be used so the `#NAME::Resources` type
-            // must exist
         }
 
-        let priority = task.priority;
-        if task.path.is_none() {
-            // This `const`ant is mainly used to make sure the user doesn't
-            // forget to set a task handler using the `task!` macro. They'll get
-            // an error if they do.
-            items.push(quote! {
-                #[deny(dead_code)]
-                pub const #name: u8 = #priority;
-            });
+        if has_resources {
+            tys.push(quote!(#name::Resources));
+            exprs.push(quote!(#name::Resources::new()));
         }
 
+        let path = &task.path;
+        let _name = Ident::new(format!("_{}", name));
+        let export_name =
+            Lit::Str(name.as_ref().to_owned(), StrStyle::Cooked);
+        root.push(quote! {
+            #[allow(non_snake_case)]
+            #[allow(unsafe_code)]
+            #[export_name = #export_name]
+            pub unsafe extern "C" fn #_name() {
+                let f: fn(#(#tys,)*) = #path;
+
+                f(#(#exprs,)*)
+            }
+        });
+
         root.push(quote!{
             #[allow(non_snake_case)]
             #[allow(unsafe_code)]