diff --git a/src/env.cpp b/src/env.cpp
index ce586e3d2..49fc2c75a 100644
--- a/src/env.cpp
+++ b/src/env.cpp
@@ -600,6 +600,7 @@ class env_scoped_impl_t : public environment_t, noncopyable_t {
     // query.
     maybe_t<env_var_t> try_get_computed(const wcstring &key) const;
     maybe_t<env_var_t> try_get_local(const wcstring &key) const;
+    maybe_t<env_var_t> try_get_function(const wcstring &key) const;
     maybe_t<env_var_t> try_get_global(const wcstring &key) const;
     maybe_t<env_var_t> try_get_universal(const wcstring &key) const;
 
@@ -772,6 +773,22 @@ maybe_t<env_var_t> env_scoped_impl_t::try_get_local(const wcstring &key) const {
     return entry; // this is either the entry or none() from find_entry
 }
 
+maybe_t<env_var_t> env_scoped_impl_t::try_get_function(const wcstring &key) const {
+    maybe_t<env_var_t> entry;
+    auto node = locals_;
+    while (node->next) {
+        node = node->next;
+        // The first node that introduces a new scope is ours.
+        // If this doesn't happen, we go on until we've reached the
+        // topmost local scope.
+        if (node->new_scope) break;
+    }
+    for (auto cur = node; cur; cur=cur->next) {
+        if ((entry = cur->find_entry(key))) break;
+    }
+    return entry; // this is either the entry or none() from find_entry
+}
+
 maybe_t<env_var_t> env_scoped_impl_t::try_get_global(const wcstring &key) const {
     return globals_->find_entry(key);
 }
@@ -792,6 +809,9 @@ maybe_t<env_var_t> env_scoped_impl_t::get(const wcstring &key, env_mode_flags_t
     if (!result && query.local) {
         result = try_get_local(key);
     }
+    if (!result && query.function) {
+        result = try_get_function(key);
+    }
     if (!result && query.global) {
         result = try_get_global(key);
     }
diff --git a/tests/checks/set.fish b/tests/checks/set.fish
index 31f82b3d5..65cb9b1f5 100644
--- a/tests/checks/set.fish
+++ b/tests/checks/set.fish
@@ -868,6 +868,29 @@ end
 
 erase-funcvar
 
+set -f foo
+set -l banana
+set -g global
+begin
+    set -qf foo
+    and echo foo is function scoped
+    # CHECK: foo is function scoped
+
+    set -l localvar414
+    set -qf localvar414
+    or echo localvar414 is not function scoped
+    # CHECK: localvar414 is not function scoped
+
+    set -qf banana
+    and echo banana is function scoped
+    # CHECK: banana is function scoped
+
+    set -l global
+    set -qf global
+    or echo global is not function scoped
+    # CHECK: global is not function scoped
+end
+
 set --query $this_is_not_set
 echo $status
 # CHECK: 255