diff --git a/src/libexpr/attr-set.hh b/src/libexpr/attr-set.hh
index f5651891f04845417e1fd6b44df934653dd632f8..c601d09c2ad495a872c69967a809110e3c1419b5 100644
--- a/src/libexpr/attr-set.hh
+++ b/src/libexpr/attr-set.hh
@@ -76,11 +76,10 @@ public:
     {
         auto a = get(name);
         if (!a)
-            throw Error(
-                ErrorInfo { 
-                    .hint = hintfmt("attribute '%s' missing", name),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw Error({
+                .hint = hintfmt("attribute '%s' missing", name),
+                .nixCode = NixCode { .errPos = pos }
+            });
 
         return *a;
     }
diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh
index eee49e02e3ea3f5c0c8f2e4a3ddcafb23d684e96..3d544c903fba2e148958b0ecfecbbd6caeaeb763 100644
--- a/src/libexpr/eval-inline.hh
+++ b/src/libexpr/eval-inline.hh
@@ -9,11 +9,10 @@ namespace nix {
 
 LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s))
 {
-    throw EvalError(
-        ErrorInfo { 
-            .hint = hintfmt(s),
-            .nixCode = NixCode { .errPos = pos }
-        });
+    throw EvalError({
+        .hint = hintfmt(s),
+        .nixCode = NixCode { .errPos = pos }
+    });
 }
 
 LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v))
@@ -24,11 +23,10 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v))
 
 LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const Value & v))
 {
-    throw TypeError(
-        ErrorInfo { 
-            .hint = hintfmt(s, showType(v)),
-            .nixCode = NixCode { .errPos = pos }
-        });
+    throw TypeError({
+        .hint = hintfmt(s, showType(v)),
+        .nixCode = NixCode { .errPos = pos }
+    });
 }
 
 
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 75e6a23a1b9fdb34cc6031718f87623e3d090776..8e71db2b872591b52c9169dadeac34e42c0a7ca1 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -519,30 +519,27 @@ LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2, con
 
 LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const string & s2, const string & s3))
 {
-    throw EvalError(
-        ErrorInfo { 
-            .hint = hintfmt(s, s2, s3),
-            .nixCode = NixCode { .errPos = pos }
-        });
+    throw EvalError({
+        .hint = hintfmt(s, s2, s3),
+        .nixCode = NixCode { .errPos = pos }
+    });
 }
 
 LocalNoInlineNoReturn(void throwEvalError(const Pos & p1, const char * s, const Symbol & sym, const Pos & p2))
 {
     // p1 is where the error occurred; p2 is a position mentioned in the message.
-    throw EvalError(
-        ErrorInfo { 
-            .hint = hintfmt(s, sym, p2),
-            .nixCode = NixCode { .errPos = p1 }
-        });
+    throw EvalError({
+        .hint = hintfmt(s, sym, p2),
+        .nixCode = NixCode { .errPos = p1 }
+    });
 }
 
 LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s))
 {
-    throw TypeError(
-        ErrorInfo { 
-            .hint = hintfmt(s),
-            .nixCode = NixCode { .errPos = pos }
-        });
+    throw TypeError({
+        .hint = hintfmt(s),
+        .nixCode = NixCode { .errPos = pos }
+    });
 }
 
 LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s1))
@@ -552,29 +549,26 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s1))
 
 LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const ExprLambda & fun, const Symbol & s2))
 {
-    throw TypeError(
-        ErrorInfo { 
-            .hint = hintfmt(s, fun.showNamePos(), s2),
-            .nixCode = NixCode { .errPos = pos }
-        });
+    throw TypeError({
+        .hint = hintfmt(s, fun.showNamePos(), s2),
+        .nixCode = NixCode { .errPos = pos }
+    });
 }
 
 LocalNoInlineNoReturn(void throwAssertionError(const Pos & pos, const char * s, const string & s1))
 {
-    throw AssertionError(
-        ErrorInfo { 
-            .hint = hintfmt(s, s1),
-            .nixCode = NixCode { .errPos = pos }
-        });
+    throw AssertionError({
+        .hint = hintfmt(s, s1),
+        .nixCode = NixCode { .errPos = pos }
+    });
 }
 
 LocalNoInlineNoReturn(void throwUndefinedVarError(const Pos & pos, const char * s, const string & s1))
 {
-    throw UndefinedVarError(
-        ErrorInfo { 
-            .hint = hintfmt(s, s1),
-            .nixCode = NixCode { .errPos = pos }
-        });
+    throw UndefinedVarError({
+        .hint = hintfmt(s, s1),
+        .nixCode = NixCode { .errPos = pos }
+    });
 }
 
 LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2))
@@ -1593,7 +1587,7 @@ string EvalState::forceStringNoCtx(Value & v, const Pos & pos)
     string s = forceString(v, pos);
     if (v.string.context) {
         if (pos)
-            throwEvalError(pos, "the string '%1%' is not allowed to refer to a store path (such as '%2%')", 
+            throwEvalError(pos, "the string '%1%' is not allowed to refer to a store path (such as '%2%')",
                 v.string.s, v.string.context[0]);
         else
             throwEvalError("the string '%1%' is not allowed to refer to a store path (such as '%2%')",
@@ -1919,11 +1913,10 @@ void EvalState::printStats()
 
 string ExternalValueBase::coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore) const
 {
-    throw TypeError(
-        ErrorInfo { 
-            .hint = hintfmt("cannot coerce %1% to a string", showType()),
-            .nixCode = NixCode { .errPos = pos }
-        });
+    throw TypeError({
+        .hint = hintfmt("cannot coerce %1% to a string", showType()),
+        .nixCode = NixCode { .errPos = pos }
+    });
 }
 
 
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index 91a50830542cb65cb97924a4f979ba0ec2d65efd..5b2dd9751e3bbbcd52b724c5707db8672b856fb9 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -268,11 +268,10 @@ void ExprVar::bindVars(const StaticEnv & env)
        enclosing `with'.  If there is no `with', then we can issue an
        "undefined variable" error now. */
     if (withLevel == -1) 
-        throw UndefinedVarError(
-            ErrorInfo {
-                .hint = hintfmt("undefined variable '%1%'", name),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw UndefinedVarError({
+            .hint = hintfmt("undefined variable '%1%'", name),
+            .nixCode = NixCode { .errPos = pos }
+        });
     fromWith = true;
     this->level = withLevel;
 }
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 47d0e85ec7f2f487df9bb8b5e4541307f9a1105e..ec6fd3190be4a84f3f81de49ebe4ef49f30dfa77 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -236,11 +236,10 @@ struct ExprLambda : Expr
         : pos(pos), arg(arg), matchAttrs(matchAttrs), formals(formals), body(body)
     {
         if (!arg.empty() && formals && formals->argNames.find(arg) != formals->argNames.end())
-            throw ParseError(
-                ErrorInfo {
-                    .hint = hintfmt("duplicate formal function argument '%1%'", arg),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw ParseError({
+                .hint = hintfmt("duplicate formal function argument '%1%'", arg),
+                .nixCode = NixCode { .errPos = pos }
+            });
     };
     void setName(Symbol & name);
     string showNamePos() const;
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 0417a3c217fb8eca7252481482265503cd71a601..a1188dec03e082a7e9430bea2b5b971429e9c8c3 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -64,23 +64,20 @@ namespace nix {
 
 static void dupAttr(const AttrPath & attrPath, const Pos & pos, const Pos & prevPos)
 {
-    throw ParseError(
-        ErrorInfo {
-            .hint = hintfmt("attribute '%1%' already defined at %2%",
-                showAttrPath(attrPath), prevPos),
-            .nixCode = NixCode { .errPos = pos },
-        });
+    throw ParseError({
+        .hint = hintfmt("attribute '%1%' already defined at %2%",
+            showAttrPath(attrPath), prevPos),
+        .nixCode = NixCode { .errPos = pos },
+    });
 }
 
 
 static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos)
 {
-    throw ParseError(
-        ErrorInfo {
-            .hint = hintfmt("attribute '%1%' already defined at %2%",
-                attr, prevPos),
-            .nixCode = NixCode { .errPos = pos },
-        });
+    throw ParseError({
+        .hint = hintfmt("attribute '%1%' already defined at %2%", attr, prevPos),
+        .nixCode = NixCode { .errPos = pos },
+    });
 }
 
 
@@ -148,12 +145,11 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
 static void addFormal(const Pos & pos, Formals * formals, const Formal & formal)
 {
     if (!formals->argNames.insert(formal.name).second)
-        throw ParseError(
-            ErrorInfo {
-                .hint = hintfmt("duplicate formal function argument '%1%'",
-                    formal.name),
-                .nixCode = NixCode { .errPos = pos },
-            });
+        throw ParseError({
+            .hint = hintfmt("duplicate formal function argument '%1%'",
+                formal.name),
+            .nixCode = NixCode { .errPos = pos },
+        });
     formals->formals.push_front(formal);
 }
 
@@ -261,10 +257,10 @@ static inline Pos makeCurPos(const YYLTYPE & loc, ParseData * data)
 
 void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * error)
 {
-    data->error = ErrorInfo { 
+    data->error = {
         .hint = hintfmt(error),
         .nixCode = NixCode { .errPos = makeCurPos(*loc, data) }
-        };
+    };
 }
 
 
@@ -341,11 +337,10 @@ expr_function
     { $$ = new ExprWith(CUR_POS, $2, $4); }
   | LET binds IN expr_function
     { if (!$2->dynamicAttrs.empty())
-        throw ParseError(
-            ErrorInfo {
-                .hint = hintfmt("dynamic attributes not allowed in let"),
-                .nixCode = NixCode { .errPos = CUR_POS },
-            });
+        throw ParseError({
+            .hint = hintfmt("dynamic attributes not allowed in let"),
+            .nixCode = NixCode { .errPos = CUR_POS },
+        });
       $$ = new ExprLet($2, $4);
     }
   | expr_if
@@ -422,11 +417,10 @@ expr_simple
   | URI {
       static bool noURLLiterals = settings.isExperimentalFeatureEnabled("no-url-literals");
       if (noURLLiterals)
-          throw ParseError(
-              ErrorInfo { 
-                  .hint = hintfmt("URL literals are disabled"),
-                  .nixCode = NixCode { .errPos = CUR_POS }
-              });
+          throw ParseError({
+              .hint = hintfmt("URL literals are disabled"),
+              .nixCode = NixCode { .errPos = CUR_POS }
+          });
       $$ = new ExprString(data->symbols.create($1));
   }
   | '(' expr ')' { $$ = $2; }
@@ -496,11 +490,10 @@ attrs
           $$->push_back(AttrName(str->s));
           delete str;
       } else
-          throw ParseError(
-              ErrorInfo {
-                  .hint = hintfmt("dynamic attributes not allowed in inherit"),
-                  .nixCode = NixCode { .errPos = makeCurPos(@2, data) },
-              });
+          throw ParseError({
+              .hint = hintfmt("dynamic attributes not allowed in inherit"),
+              .nixCode = NixCode { .errPos = makeCurPos(@2, data) },
+          });
     }
   | { $$ = new AttrPath; }
   ;
@@ -695,11 +688,10 @@ Path EvalState::findFile(SearchPath & searchPath, const string & path, const Pos
         Path res = r.second + suffix;
         if (pathExists(res)) return canonPath(res);
     }
-    throw ThrownError(
-        ErrorInfo { 
-            .hint = hintfmt("file '%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)", path),
-            .nixCode = NixCode { .errPos = pos }
-        });
+    throw ThrownError({
+        .hint = hintfmt("file '%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)", path),
+        .nixCode = NixCode { .errPos = pos }
+    });
 }
 
 
@@ -715,10 +707,9 @@ std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathEl
             res = { true, store->toRealPath(fetchers::downloadTarball(
                         store, resolveUri(elem.second), "source", false).storePath) };
         } catch (FileTransferError & e) {
-            logWarning(
-                ErrorInfo { 
-                    .name = "Entry download",
-                    .hint = hintfmt("Nix search path entry '%1%' cannot be downloaded, ignoring", elem.second)
+            logWarning({
+                .name = "Entry download",
+                .hint = hintfmt("Nix search path entry '%1%' cannot be downloaded, ignoring", elem.second)
             });
             res = { false, "" };
         }
@@ -727,10 +718,9 @@ std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathEl
         if (pathExists(path))
             res = { true, path };
         else {
-            logWarning(
-                ErrorInfo { 
-                    .name = "Entry not found",
-                    .hint = hintfmt("warning: Nix search path entry '%1%' does not exist, ignoring", elem.second)
+            logWarning({
+                .name = "Entry not found",
+                .hint = hintfmt("warning: Nix search path entry '%1%' does not exist, ignoring", elem.second)
             });
             res = { false, "" };
         }
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 23ab7dec656ea3c0eefdcf93b0f6680716920c3a..62e5163c902e0f39a585c0c07648c48ea5b9d220 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -93,12 +93,10 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
     try {
         state.realiseContext(context);
     } catch (InvalidPathError & e) {
-        throw EvalError(
-            ErrorInfo { 
-                .hint = hintfmt("cannot import '%1%', since path '%2%' is not valid",
-                        path, e.path),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt("cannot import '%1%', since path '%2%' is not valid", path, e.path),
+            .nixCode = NixCode { .errPos = pos }
+        });
     }
 
     Path realPath = state.checkSourcePath(state.toRealPath(path, context));
@@ -174,13 +172,12 @@ void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value
     try {
         state.realiseContext(context);
     } catch (InvalidPathError & e) {
-        throw EvalError(
-            ErrorInfo {
-                .hint = hintfmt(
-                    "cannot import '%1%', since path '%2%' is not valid",
-                    path, e.path),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt(
+                "cannot import '%1%', since path '%2%' is not valid",
+                path, e.path),
+            .nixCode = NixCode { .errPos = pos }
+        });
     }
 
     path = state.checkSourcePath(path);
@@ -215,11 +212,10 @@ void prim_exec(EvalState & state, const Pos & pos, Value * * args, Value & v)
     auto elems = args[0]->listElems();
     auto count = args[0]->listSize();
     if (count == 0) {
-        throw EvalError(
-            ErrorInfo {
-                .hint = hintfmt("at least one argument to 'exec' required"),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt("at least one argument to 'exec' required"),
+            .nixCode = NixCode { .errPos = pos }
+        });
     }
     PathSet context;
     auto program = state.coerceToString(pos, *elems[0], context, false, false);
@@ -230,12 +226,12 @@ void prim_exec(EvalState & state, const Pos & pos, Value * * args, Value & v)
     try {
         state.realiseContext(context);
     } catch (InvalidPathError & e) {
-        throw EvalError(
-            ErrorInfo {
-                .hint = hintfmt("cannot execute '%1%', since path '%2%' is not valid",
-                    program, e.path),
-                .nixCode = NixCode { .errPos = pos }
-            });}
+        throw EvalError({
+            .hint = hintfmt("cannot execute '%1%', since path '%2%' is not valid",
+                program, e.path),
+            .nixCode = NixCode { .errPos = pos }
+        });
+    }
 
     auto output = runProgram(program, true, commandArgs);
     Expr * parsed;
@@ -386,11 +382,10 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar
     Bindings::iterator startSet =
         args[0]->attrs->find(state.symbols.create("startSet"));
     if (startSet == args[0]->attrs->end())
-        throw EvalError(
-            ErrorInfo {
-                .hint = hintfmt("attribute 'startSet' required"),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt("attribute 'startSet' required"),
+            .nixCode = NixCode { .errPos = pos }
+        });
     state.forceList(*startSet->value, pos);
 
     ValueList workSet;
@@ -401,11 +396,10 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar
     Bindings::iterator op =
         args[0]->attrs->find(state.symbols.create("operator"));
     if (op == args[0]->attrs->end())
-        throw EvalError(
-            ErrorInfo {
-                .hint = hintfmt("attribute 'operator' required"),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt("attribute 'operator' required"),
+            .nixCode = NixCode { .errPos = pos }
+        });
     state.forceValue(*op->value, pos);
 
     /* Construct the closure by applying the operator to element of
@@ -424,11 +418,10 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar
         Bindings::iterator key =
             e->attrs->find(state.symbols.create("key"));
         if (key == e->attrs->end())
-            throw EvalError(
-                ErrorInfo {
-                    .hint = hintfmt("attribute 'key' required"),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("attribute 'key' required"),
+                .nixCode = NixCode { .errPos = pos }
+            });
         state.forceValue(*key->value, pos);
 
         if (!doneKeys.insert(key->value).second) continue;
@@ -560,11 +553,10 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
     /* Figure out the name first (for stack backtraces). */
     Bindings::iterator attr = args[0]->attrs->find(state.sName);
     if (attr == args[0]->attrs->end())
-        throw EvalError(
-            ErrorInfo {
-                .hint = hintfmt("required attribute 'name' missing"),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt("required attribute 'name' missing"),
+            .nixCode = NixCode { .errPos = pos }
+        });
     string drvName;
     Pos & posDrvName(*attr->pos);
     try {
@@ -607,42 +599,38 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
         auto handleHashMode = [&](const std::string & s) {
             if (s == "recursive") ingestionMethod = FileIngestionMethod::Recursive;
             else if (s == "flat") ingestionMethod = FileIngestionMethod::Flat;
-            else 
-                throw EvalError(
-                    ErrorInfo { 
-                        .hint = hintfmt("invalid value '%s' for 'outputHashMode' attribute", s),
-                        .nixCode = NixCode { .errPos = posDrvName }
-                    });
+            else
+                throw EvalError({
+                    .hint = hintfmt("invalid value '%s' for 'outputHashMode' attribute", s),
+                    .nixCode = NixCode { .errPos = posDrvName }
+                });
         };
 
         auto handleOutputs = [&](const Strings & ss) {
             outputs.clear();
             for (auto & j : ss) {
                 if (outputs.find(j) != outputs.end())
-                    throw EvalError(
-                        ErrorInfo { 
-                            .hint = hintfmt("duplicate derivation output '%1%'", j),
-                            .nixCode = NixCode { .errPos = posDrvName }
-                        });
+                    throw EvalError({
+                        .hint = hintfmt("duplicate derivation output '%1%'", j),
+                        .nixCode = NixCode { .errPos = posDrvName }
+                    });
                 /* !!! Check whether j is a valid attribute
                    name. */
                 /* Derivations cannot be named ‘drv’, because
                    then we'd have an attribute ‘drvPath’ in
                    the resulting set. */
                 if (j == "drv")
-                    throw EvalError(
-                        ErrorInfo { 
-                            .hint = hintfmt("invalid derivation output name 'drv'" ),
-                            .nixCode = NixCode { .errPos = posDrvName }
-                        });
+                    throw EvalError({
+                        .hint = hintfmt("invalid derivation output name 'drv'" ),
+                        .nixCode = NixCode { .errPos = posDrvName }
+                    });
                 outputs.insert(j);
             }
             if (outputs.empty())
-                throw EvalError(
-                    ErrorInfo { 
-                        .hint = hintfmt("derivation cannot have an empty set of outputs"),
-                        .nixCode = NixCode { .errPos = posDrvName }
-                    });
+                throw EvalError({
+                    .hint = hintfmt("derivation cannot have an empty set of outputs"),
+                    .nixCode = NixCode { .errPos = posDrvName }
+                });
         };
 
         try {
@@ -754,35 +742,31 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
 
     /* Do we have all required attributes? */
     if (drv.builder == "")
-        throw EvalError(
-            ErrorInfo { 
-                .hint = hintfmt("required attribute 'builder' missing"),
-                .nixCode = NixCode { .errPos = posDrvName }
-            });
+        throw EvalError({
+            .hint = hintfmt("required attribute 'builder' missing"),
+            .nixCode = NixCode { .errPos = posDrvName }
+        });
 
     if (drv.platform == "")
-        throw EvalError(
-            ErrorInfo { 
-                .hint = hintfmt("required attribute 'system' missing"),
-                .nixCode = NixCode { .errPos = posDrvName }
-            });
+        throw EvalError({
+            .hint = hintfmt("required attribute 'system' missing"),
+            .nixCode = NixCode { .errPos = posDrvName }
+        });
 
     /* Check whether the derivation name is valid. */
     if (isDerivation(drvName))
-        throw EvalError(
-            ErrorInfo { 
-                .hint = hintfmt("derivation names are not allowed to end in '%s'", drvExtension),
-                .nixCode = NixCode { .errPos = posDrvName }
-            });
+        throw EvalError({
+            .hint = hintfmt("derivation names are not allowed to end in '%s'", drvExtension),
+            .nixCode = NixCode { .errPos = posDrvName }
+        });
 
     if (outputHash) {
         /* Handle fixed-output derivations. */
         if (outputs.size() != 1 || *(outputs.begin()) != "out")
-            throw Error(
-                ErrorInfo { 
-                    .hint = hintfmt("multiple outputs are not supported in fixed-output derivations"),
-                    .nixCode = NixCode { .errPos = posDrvName }
-                });
+            throw Error({
+                .hint = hintfmt("multiple outputs are not supported in fixed-output derivations"),
+                .nixCode = NixCode { .errPos = posDrvName }
+            });
 
         HashType ht = outputHashAlgo.empty() ? htUnknown : parseHashType(outputHashAlgo);
 
@@ -887,11 +871,10 @@ static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, V
        e.g. nix-push does the right thing. */
     if (!state.store->isStorePath(path)) path = canonPath(path, true);
     if (!state.store->isInStore(path))
-        throw EvalError(
-            ErrorInfo {
-                .hint = hintfmt("path '%1%' is not in the Nix store", path),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt("path '%1%' is not in the Nix store", path),
+            .nixCode = NixCode { .errPos = pos }
+        });
     Path path2 = state.store->toStorePath(path);
     if (!settings.readOnlyMode)
         state.store->ensurePath(state.store->parseStorePath(path2));
@@ -907,13 +890,12 @@ static void prim_pathExists(EvalState & state, const Pos & pos, Value * * args,
     try {
         state.realiseContext(context);
     } catch (InvalidPathError & e) {
-        throw EvalError(
-            ErrorInfo {
-                .hint = hintfmt(
-                    "cannot check the existence of '%1%', since path '%2%' is not valid", 
-                    path, e.path),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt(
+                "cannot check the existence of '%1%', since path '%2%' is not valid",
+                path, e.path),
+            .nixCode = NixCode { .errPos = pos }
+        });
     }
 
     try {
@@ -956,13 +938,11 @@ static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Va
     try {
         state.realiseContext(context);
     } catch (InvalidPathError & e) {
-        throw EvalError(
-            ErrorInfo {
-                .hint = hintfmt("cannot read '%1%', since path '%2%' is not valid"
-                     , path, e.path),
-                .nixCode = NixCode { .errPos = pos }
-            });
- }
+        throw EvalError({
+            .hint = hintfmt("cannot read '%1%', since path '%2%' is not valid", path, e.path),
+            .nixCode = NixCode { .errPos = pos }
+        });
+    }
     string s = readFile(state.checkSourcePath(state.toRealPath(path, context)));
     if (s.find((char) 0) != string::npos)
         throw Error("the contents of the file '%1%' cannot be represented as a Nix string", path);
@@ -989,11 +969,10 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
 
         i = v2.attrs->find(state.symbols.create("path"));
         if (i == v2.attrs->end())
-            throw EvalError(
-                ErrorInfo {
-                    .hint = hintfmt("attribute 'path' missing"),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("attribute 'path' missing"),
+                .nixCode = NixCode { .errPos = pos }
+            });
 
         PathSet context;
         string path = state.coerceToString(pos, *i->value, context, false, false);
@@ -1001,12 +980,10 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
         try {
             state.realiseContext(context);
         } catch (InvalidPathError & e) {
-            throw EvalError(
-                ErrorInfo {
-                    .hint = hintfmt("cannot find '%1%', since path '%2%' is not valid",
-                        path, e.path),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("cannot find '%1%', since path '%2%' is not valid", path, e.path),
+                .nixCode = NixCode { .errPos = pos }
+            });
         }
 
         searchPath.emplace_back(prefix, path);
@@ -1023,11 +1000,10 @@ static void prim_hashFile(EvalState & state, const Pos & pos, Value * * args, Va
     string type = state.forceStringNoCtx(*args[0], pos);
     HashType ht = parseHashType(type);
     if (ht == htUnknown)
-      throw Error(
-          ErrorInfo {
-              .hint = hintfmt("unknown hash type '%1%'", type),
-              .nixCode = NixCode { .errPos = pos }
-          });
+      throw Error({
+          .hint = hintfmt("unknown hash type '%1%'", type),
+          .nixCode = NixCode { .errPos = pos }
+      });
 
     PathSet context; // discarded
     Path p = state.coerceToPath(pos, *args[1], context);
@@ -1043,12 +1019,10 @@ static void prim_readDir(EvalState & state, const Pos & pos, Value * * args, Val
     try {
         state.realiseContext(ctx);
     } catch (InvalidPathError & e) {
-        throw EvalError(
-            ErrorInfo {
-                .hint = hintfmt("cannot read '%1%', since path '%2%' is not valid",
-                        path, e.path),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt("cannot read '%1%', since path '%2%' is not valid", path, e.path),
+            .nixCode = NixCode { .errPos = pos }
+        });
     }
 
     DirEntries entries = readDirectory(state.checkSourcePath(path));
@@ -1118,15 +1092,13 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu
 
     for (auto path : context) {
         if (path.at(0) != '/')
-            throw EvalError(
-                ErrorInfo { 
-                    .hint = hintfmt(
-                        "in 'toFile': the file named '%1%' must not contain a reference "
-                        "to a derivation but contains (%2%)",
-                        name,
-                        path),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw EvalError( {
+                .hint = hintfmt(
+                    "in 'toFile': the file named '%1%' must not contain a reference "
+                    "to a derivation but contains (%2%)",
+                    name, path),
+                .nixCode = NixCode { .errPos = pos }
+            });
         refs.insert(state.store->parseStorePath(path));
     }
 
@@ -1194,21 +1166,19 @@ static void prim_filterSource(EvalState & state, const Pos & pos, Value * * args
     PathSet context;
     Path path = state.coerceToPath(pos, *args[1], context);
     if (!context.empty())
-        throw EvalError(
-            ErrorInfo { 
-                .hint = hintfmt("string '%1%' cannot refer to other paths", path),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt("string '%1%' cannot refer to other paths", path),
+            .nixCode = NixCode { .errPos = pos }
+        });
 
     state.forceValue(*args[0], pos);
     if (args[0]->type != tLambda)
-        throw TypeError(
-            ErrorInfo { 
-                .hint = hintfmt(
-                    "first argument in call to 'filterSource' is not a function but %1%", 
-                    showType(*args[0])),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw TypeError({
+            .hint = hintfmt(
+                "first argument in call to 'filterSource' is not a function but %1%",
+                showType(*args[0])),
+            .nixCode = NixCode { .errPos = pos }
+        });
 
     addPath(state, pos, std::string(baseNameOf(path)), path, args[0], FileIngestionMethod::Recursive, Hash(), v);
 }
@@ -1228,12 +1198,10 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value
             PathSet context;
             path = state.coerceToPath(*attr.pos, *attr.value, context);
             if (!context.empty())
-                throw EvalError(
-                    ErrorInfo { 
-                        .hint = hintfmt("string '%1%' cannot refer to other paths", 
-                            path),
-                        .nixCode = NixCode { .errPos = *attr.pos }
-                    });
+                throw EvalError({
+                    .hint = hintfmt("string '%1%' cannot refer to other paths", path),
+                    .nixCode = NixCode { .errPos = *attr.pos }
+                });
         } else if (attr.name == state.sName)
             name = state.forceStringNoCtx(*attr.value, *attr.pos);
         else if (n == "filter") {
@@ -1244,19 +1212,16 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value
         else if (n == "sha256")
             expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256);
         else
-            throw EvalError(
-                ErrorInfo { 
-                    .hint = hintfmt("unsupported argument '%1%' to 'addPath'",
-                        attr.name),
-                    .nixCode = NixCode { .errPos = *attr.pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("unsupported argument '%1%' to 'addPath'", attr.name),
+                .nixCode = NixCode { .errPos = *attr.pos }
+            });
     }
     if (path.empty())
-        throw EvalError(
-            ErrorInfo { 
-                .hint = hintfmt("'path' required"),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt("'path' required"),
+            .nixCode = NixCode { .errPos = pos }
+        });
     if (name.empty())
         name = baseNameOf(path);
 
@@ -1314,11 +1279,10 @@ void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v)
     // !!! Should we create a symbol here or just do a lookup?
     Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr));
     if (i == args[1]->attrs->end())
-        throw EvalError(
-            ErrorInfo { 
-                .hint = hintfmt("attribute '%1%' missing", attr),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt("attribute '%1%' missing", attr),
+            .nixCode = NixCode { .errPos = pos }
+        });
     // !!! add to stack trace?
     if (state.countCalls && i->pos) state.attrSelects[*i->pos]++;
     state.forceValue(*i->value, pos);
@@ -1398,22 +1362,20 @@ static void prim_listToAttrs(EvalState & state, const Pos & pos, Value * * args,
 
         Bindings::iterator j = v2.attrs->find(state.sName);
         if (j == v2.attrs->end())
-            throw TypeError(
-                ErrorInfo { 
-                    .hint = hintfmt("'name' attribute missing in a call to 'listToAttrs'"), 
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw TypeError({
+                .hint = hintfmt("'name' attribute missing in a call to 'listToAttrs'"),
+                .nixCode = NixCode { .errPos = pos }
+            });
         string name = state.forceStringNoCtx(*j->value, pos);
 
         Symbol sym = state.symbols.create(name);
         if (seen.insert(sym).second) {
             Bindings::iterator j2 = v2.attrs->find(state.symbols.create(state.sValue));
             if (j2 == v2.attrs->end())
-                throw TypeError(
-                    ErrorInfo { 
-                        .hint = hintfmt("'value' attribute missing in a call to 'listToAttrs'"), 
-                        .nixCode = NixCode { .errPos = pos }
-                    });
+                throw TypeError({
+                    .hint = hintfmt("'value' attribute missing in a call to 'listToAttrs'"),
+                    .nixCode = NixCode { .errPos = pos }
+                });
             v.attrs->push_back(Attr(sym, j2->value, j2->pos));
         }
     }
@@ -1486,11 +1448,10 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args
 {
     state.forceValue(*args[0], pos);
     if (args[0]->type != tLambda)
-        throw TypeError(
-            ErrorInfo { 
-                .hint = hintfmt("'functionArgs' requires a function"), 
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw TypeError({
+            .hint = hintfmt("'functionArgs' requires a function"),
+            .nixCode = NixCode { .errPos = pos }
+        });
 
     if (!args[0]->lambda.fun->matchAttrs) {
         state.mkAttrs(v, 0);
@@ -1543,11 +1504,10 @@ static void elemAt(EvalState & state, const Pos & pos, Value & list, int n, Valu
 {
     state.forceList(list, pos);
     if (n < 0 || (unsigned int) n >= list.listSize())
-        throw Error(
-            ErrorInfo { 
-                .hint = hintfmt("list index %1% is out of bounds", n), 
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw Error({
+            .hint = hintfmt("list index %1% is out of bounds", n),
+            .nixCode = NixCode { .errPos = pos }
+        });
     state.forceValue(*list.listElems()[n], pos);
     v = *list.listElems()[n];
 }
@@ -1574,11 +1534,10 @@ static void prim_tail(EvalState & state, const Pos & pos, Value * * args, Value
 {
     state.forceList(*args[0], pos);
     if (args[0]->listSize() == 0)
-        throw Error(
-            ErrorInfo { 
-                .hint = hintfmt("'tail' called on an empty list"), 
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw Error({
+            .hint = hintfmt("'tail' called on an empty list"),
+            .nixCode = NixCode { .errPos = pos }
+        });
 
     state.mkList(v, args[0]->listSize() - 1);
     for (unsigned int n = 0; n < v.listSize(); ++n)
@@ -1720,12 +1679,10 @@ static void prim_genList(EvalState & state, const Pos & pos, Value * * args, Val
     auto len = state.forceInt(*args[1], pos);
 
     if (len < 0)
-        throw EvalError(
-            ErrorInfo { 
-                .hint = hintfmt("cannot create list of size %1%", len), 
-                .nixCode = NixCode { .errPos = pos }
-            });
-
+        throw EvalError({
+            .hint = hintfmt("cannot create list of size %1%", len),
+            .nixCode = NixCode { .errPos = pos }
+        });
 
     state.mkList(v, len);
 
@@ -1883,12 +1840,11 @@ static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value &
     state.forceValue(*args[1], pos);
 
     NixFloat f2 = state.forceFloat(*args[1], pos);
-    if (f2 == 0) 
-        throw EvalError(
-            ErrorInfo { 
-                .hint = hintfmt("division by zero"), 
-                .nixCode = NixCode { .errPos = pos }
-            });
+    if (f2 == 0)
+        throw EvalError({
+            .hint = hintfmt("division by zero"),
+            .nixCode = NixCode { .errPos = pos }
+        });
 
     if (args[0]->type == tFloat || args[1]->type == tFloat) {
         mkFloat(v, state.forceFloat(*args[0], pos) / state.forceFloat(*args[1], pos));
@@ -1897,11 +1853,10 @@ static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value &
         NixInt i2 = state.forceInt(*args[1], pos);
         /* Avoid division overflow as it might raise SIGFPE. */
         if (i1 == std::numeric_limits<NixInt>::min() && i2 == -1)
-            throw EvalError(
-                ErrorInfo { 
-                    .hint = hintfmt("overflow in integer division"), 
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("overflow in integer division"),
+                .nixCode = NixCode { .errPos = pos }
+            });
 
         mkInt(v, i1 / i2);
     }
@@ -1958,12 +1913,11 @@ static void prim_substring(EvalState & state, const Pos & pos, Value * * args, V
     PathSet context;
     string s = state.coerceToString(pos, *args[2], context);
 
-    if (start < 0) 
-        throw EvalError(
-            ErrorInfo { 
-                .hint = hintfmt("negative start position in 'substring'"), 
-                .nixCode = NixCode { .errPos = pos }
-            });
+    if (start < 0)
+        throw EvalError({
+            .hint = hintfmt("negative start position in 'substring'"),
+            .nixCode = NixCode { .errPos = pos }
+        });
 
     mkString(v, (unsigned int) start >= s.size() ? "" : string(s, start, len), context);
 }
@@ -1983,11 +1937,10 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args,
     string type = state.forceStringNoCtx(*args[0], pos);
     HashType ht = parseHashType(type);
     if (ht == htUnknown)
-        throw Error(
-            ErrorInfo { 
-                .hint = hintfmt("unknown hash type '%1%'", type), 
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw Error({
+            .hint = hintfmt("unknown hash type '%1%'", type),
+            .nixCode = NixCode { .errPos = pos }
+        });
 
     PathSet context; // discarded
     string s = state.forceString(*args[1], context, pos);
@@ -2030,17 +1983,15 @@ void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v)
     } catch (std::regex_error &e) {
         if (e.code() == std::regex_constants::error_space) {
             // limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
-            throw EvalError(
-                ErrorInfo {
-                    .hint = hintfmt("memory limit exceeded by regular expression '%s'", re),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("memory limit exceeded by regular expression '%s'", re),
+                .nixCode = NixCode { .errPos = pos }
+            });
         } else {
-            throw EvalError(
-                ErrorInfo {
-                    .hint = hintfmt("invalid regular expression '%s'", re),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("invalid regular expression '%s'", re),
+                .nixCode = NixCode { .errPos = pos }
+            });
         }
     }
 }
@@ -2105,17 +2056,15 @@ static void prim_split(EvalState & state, const Pos & pos, Value * * args, Value
     } catch (std::regex_error &e) {
         if (e.code() == std::regex_constants::error_space) {
             // limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
-            throw EvalError(
-                ErrorInfo {
-                    .hint = hintfmt("memory limit exceeded by regular expression '%s'", re),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("memory limit exceeded by regular expression '%s'", re),
+                .nixCode = NixCode { .errPos = pos }
+            });
         } else {
-            throw EvalError(
-                ErrorInfo {
-                    .hint = hintfmt("invalid regular expression '%s'", re),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("invalid regular expression '%s'", re),
+                .nixCode = NixCode { .errPos = pos }
+            });
         }
     }
 }
@@ -2146,11 +2095,10 @@ static void prim_replaceStrings(EvalState & state, const Pos & pos, Value * * ar
     state.forceList(*args[0], pos);
     state.forceList(*args[1], pos);
     if (args[0]->listSize() != args[1]->listSize())
-        throw EvalError(
-            ErrorInfo { 
-                .hint = hintfmt("'from' and 'to' arguments to 'replaceStrings' have different lengths"), 
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt("'from' and 'to' arguments to 'replaceStrings' have different lengths"),
+            .nixCode = NixCode { .errPos = pos }
+        });
 
     vector<string> from;
     from.reserve(args[0]->listSize());
diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc
index 7f895fc01594f399058391995bf78fa495a29830..efa2e9576f7c873b2b98b1b25be935fe0dc17217 100644
--- a/src/libexpr/primops/context.cc
+++ b/src/libexpr/primops/context.cc
@@ -146,11 +146,10 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg
     auto sAllOutputs = state.symbols.create("allOutputs");
     for (auto & i : *args[1]->attrs) {
         if (!state.store->isStorePath(i.name))
-            throw EvalError(
-                ErrorInfo { 
-                    .hint = hintfmt("Context key '%s' is not a store path", i.name),
-                    .nixCode = NixCode { .errPos = *i.pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("Context key '%s' is not a store path", i.name),
+                .nixCode = NixCode { .errPos = *i.pos }
+            });
         if (!settings.readOnlyMode)
             state.store->ensurePath(state.store->parseStorePath(i.name));
         state.forceAttrs(*i.value, *i.pos);
@@ -164,11 +163,10 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg
         if (iter != i.value->attrs->end()) {
             if (state.forceBool(*iter->value, *iter->pos)) {
                 if (!isDerivation(i.name)) {
-                    throw EvalError(
-                        ErrorInfo { 
-                            .hint = hintfmt("Tried to add all-outputs context of %s, which is not a derivation, to a string", i.name),
-                            .nixCode = NixCode { .errPos = *i.pos }
-                        });
+                    throw EvalError({
+                        .hint = hintfmt("Tried to add all-outputs context of %s, which is not a derivation, to a string", i.name),
+                        .nixCode = NixCode { .errPos = *i.pos }
+                    });
                 }
                 context.insert("=" + string(i.name));
             }
@@ -178,11 +176,10 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg
         if (iter != i.value->attrs->end()) {
             state.forceList(*iter->value, *iter->pos);
             if (iter->value->listSize() && !isDerivation(i.name)) {
-                throw EvalError(
-                    ErrorInfo { 
-                        .hint = hintfmt("Tried to add derivation output context of %s, which is not a derivation, to a string", i.name),
-                        .nixCode = NixCode { .errPos = *i.pos }
-                    });
+                throw EvalError({
+                    .hint = hintfmt("Tried to add derivation output context of %s, which is not a derivation, to a string", i.name),
+                    .nixCode = NixCode { .errPos = *i.pos }
+                });
             }
             for (unsigned int n = 0; n < iter->value->listSize(); ++n) {
                 auto name = state.forceStringNoCtx(*iter->value->listElems()[n], *iter->pos);
diff --git a/src/libexpr/primops/fetchGit.cc b/src/libexpr/primops/fetchGit.cc
index 52826b56ccf7e4140d2fe9873e1486a416eb5d2e..dd7229a3d54fa184788cd81cc1bc30bd6796a49a 100644
--- a/src/libexpr/primops/fetchGit.cc
+++ b/src/libexpr/primops/fetchGit.cc
@@ -35,19 +35,17 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va
             else if (n == "submodules")
                 fetchSubmodules = state.forceBool(*attr.value, *attr.pos);
             else
-                throw EvalError(
-                    ErrorInfo { 
-                        .hint = hintfmt("unsupported argument '%s' to 'fetchGit'", attr.name),
-                        .nixCode = NixCode { .errPos = *attr.pos }
-                    });
+                throw EvalError({
+                    .hint = hintfmt("unsupported argument '%s' to 'fetchGit'", attr.name),
+                    .nixCode = NixCode { .errPos = *attr.pos }
+                });
         }
 
         if (url.empty())
-            throw EvalError(
-                ErrorInfo { 
-                    .hint = hintfmt("'url' argument required"),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("'url' argument required"),
+                .nixCode = NixCode { .errPos = pos }
+            });
 
     } else
         url = state.coerceToString(pos, *args[0], context, false, false);
diff --git a/src/libexpr/primops/fetchMercurial.cc b/src/libexpr/primops/fetchMercurial.cc
index bb008ba6b366ccfec75de22cbdb2857a772ff777..9bace8f892507afde36b0fb8a7fd1efaf2b1d185 100644
--- a/src/libexpr/primops/fetchMercurial.cc
+++ b/src/libexpr/primops/fetchMercurial.cc
@@ -38,19 +38,17 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
             else if (n == "name")
                 name = state.forceStringNoCtx(*attr.value, *attr.pos);
             else
-                throw EvalError(
-                    ErrorInfo { 
-                        .hint = hintfmt("unsupported argument '%s' to 'fetchMercurial'", attr.name),
-                        .nixCode = NixCode { .errPos = *attr.pos }
-                    });
+                throw EvalError({
+                    .hint = hintfmt("unsupported argument '%s' to 'fetchMercurial'", attr.name),
+                    .nixCode = NixCode { .errPos = *attr.pos }
+                });
         }
 
         if (url.empty())
-            throw EvalError(
-                ErrorInfo { 
-                    .hint = hintfmt("'url' argument required"),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("'url' argument required"),
+                .nixCode = NixCode { .errPos = pos }
+            });
 
     } else
         url = state.coerceToString(pos, *args[0], context, false, false);
diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc
index 62bc4f4336fde295d99ef0c4ef933906691c7277..9be93710ad3b38126dd5352b98950f0e07647323 100644
--- a/src/libexpr/primops/fetchTree.cc
+++ b/src/libexpr/primops/fetchTree.cc
@@ -66,11 +66,10 @@ static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, V
         }
 
         if (!attrs.count("type"))
-            throw Error(
-                ErrorInfo {
-                    .hint = hintfmt("attribute 'type' is missing in call to 'fetchTree'"),
-                    .nixCode = NixCode { .errPos = pos }
-                    });
+            throw Error({
+                .hint = hintfmt("attribute 'type' is missing in call to 'fetchTree'"),
+                .nixCode = NixCode { .errPos = pos }
+            });
 
         input = fetchers::inputFromAttrs(attrs);
     } else
@@ -111,20 +110,17 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
             else if (n == "name")
                 name = state.forceStringNoCtx(*attr.value, *attr.pos);
             else
-                throw EvalError(
-                    ErrorInfo {
-                        .hint = hintfmt("unsupported argument '%s' to '%s'",
-                            attr.name, who),
-                        .nixCode = NixCode { .errPos = *attr.pos }
-                    });
+                throw EvalError({
+                    .hint = hintfmt("unsupported argument '%s' to '%s'", attr.name, who),
+                    .nixCode = NixCode { .errPos = *attr.pos }
+                });
             }
 
         if (!url)
-            throw EvalError(
-                ErrorInfo {
-                    .hint = hintfmt("'url' argument required"),
-                    .nixCode = NixCode { .errPos = pos }
-                });
+            throw EvalError({
+                .hint = hintfmt("'url' argument required"),
+                .nixCode = NixCode { .errPos = pos }
+            });
     } else
         url = state.forceStringNoCtx(*args[0], pos);
 
diff --git a/src/libexpr/primops/fromTOML.cc b/src/libexpr/primops/fromTOML.cc
index 9480694013046e7c07af66d90f5e66045fae70fa..7615d1379f7677ca5e6d03c671f20c4d6d46c143 100644
--- a/src/libexpr/primops/fromTOML.cc
+++ b/src/libexpr/primops/fromTOML.cc
@@ -81,11 +81,10 @@ static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Va
     try {
         visit(v, parser(tomlStream).parse());
     } catch (std::runtime_error & e) {
-        throw EvalError(
-            ErrorInfo {
-                .hint = hintfmt("while parsing a TOML string: %s", e.what()),
-                .nixCode = NixCode { .errPos = pos }
-            });
+        throw EvalError({
+            .hint = hintfmt("while parsing a TOML string: %s", e.what()),
+            .nixCode = NixCode { .errPos = pos }
+        });
     }
 }
 
diff --git a/src/libstore/builtins/buildenv.cc b/src/libstore/builtins/buildenv.cc
index 6c493ed770b38208f4d010c778dae1c7d06ea6f0..802fb87bceb5004506c683d257ff0b1898e18d58 100644
--- a/src/libstore/builtins/buildenv.cc
+++ b/src/libstore/builtins/buildenv.cc
@@ -22,10 +22,9 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
         srcFiles = readDirectory(srcDir);
     } catch (SysError & e) {
         if (e.errNo == ENOTDIR) {
-            logWarning(
-                ErrorInfo { 
-                    .name = "Create links - directory",
-                    .hint = hintfmt("not including '%s' in the user environment because it's not a directory", srcDir)
+            logWarning({
+                .name = "Create links - directory",
+                .hint = hintfmt("not including '%s' in the user environment because it's not a directory", srcDir)
             });
             return;
         }
@@ -45,10 +44,9 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
                 throw SysError("getting status of '%1%'", srcFile);
         } catch (SysError & e) {
             if (e.errNo == ENOENT || e.errNo == ENOTDIR) {
-                logWarning(
-                    ErrorInfo { 
-                        .name = "Create links - skipping symlink",
-                        .hint = hintfmt("skipping dangling symlink '%s'", dstFile)
+                logWarning({
+                    .name = "Create links - skipping symlink",
+                    .hint = hintfmt("skipping dangling symlink '%s'", dstFile)
                 });
                 continue;
             }
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 92f9328c3b8c3291158d0bcda1d3d6eaf303d2c6..04e3849f7f44cae86c307898e8b4cc51853715a3 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -129,12 +129,11 @@ Path LocalFSStore::addPermRoot(const StorePath & storePath,
     if (settings.checkRootReachability) {
         auto roots = findRoots(false);
         if (roots[storePath.clone()].count(gcRoot) == 0)
-            logWarning(
-                ErrorInfo { 
-                    .name = "GC root",
-                    .hint = hintfmt("warning: '%1%' is not in a directory where the garbage collector looks for roots; "
-                "therefore, '%2%' might be removed by the garbage collector",
-                gcRoot, printStorePath(storePath))
+            logWarning({
+                .name = "GC root",
+                .hint = hintfmt("warning: '%1%' is not in a directory where the garbage collector looks for roots; "
+                    "therefore, '%2%' might be removed by the garbage collector",
+                    gcRoot, printStorePath(storePath))
             });
     }
 
diff --git a/src/libstore/sqlite.cc b/src/libstore/sqlite.cc
index 16cdb6619b4d71daf344260b946888c92fd4f526..76c822c4e9c2ae33e0c69fb634452a9dc0fa50bd 100644
--- a/src/libstore/sqlite.cc
+++ b/src/libstore/sqlite.cc
@@ -204,10 +204,10 @@ void handleSQLiteBusy(const SQLiteBusy & e)
 
     if (now > lastWarned + 10) {
         lastWarned = now;
-        logWarning(
-            ErrorInfo { .name = "Sqlite busy",
-                        .hint = hintfmt(e.what())
-            });
+        logWarning({
+            .name = "Sqlite busy",
+            .hint = hintfmt(e.what())
+        });
     }
 
     /* Sleep for a while since retrying the transaction right away
diff --git a/src/libutil/error.hh b/src/libutil/error.hh
index 8a48fa105b10cc40be426b25b4e846e790ecb2c6..2ba3a3b338b1978b7267e8ab4ecf803c141330ce 100644
--- a/src/libutil/error.hh
+++ b/src/libutil/error.hh
@@ -22,7 +22,7 @@
 
 namespace nix {
 
-/* 
+/*
 
 This file defines two main structs/classes used in nix error handling.
 
@@ -106,7 +106,7 @@ protected:
 
     mutable std::optional<string> what_;
     const string& calcWhat() const;
-    
+
 public:
     unsigned int status = 1; // exit status
 
@@ -119,9 +119,9 @@ public:
     { }
 
     template<typename... Args>
-    BaseError(const Args & ... args)
+    BaseError(const std::string & fs, const Args & ... args)
         : err { .level = lvlError,
-                .hint = hintfmt(args...)
+                .hint = hintfmt(fs, args...)
               }
     { }
 
@@ -131,7 +131,11 @@ public:
               }
     { }
 
-    BaseError(ErrorInfo e)
+    BaseError(ErrorInfo && e)
+        : err(std::move(e))
+    { }
+
+    BaseError(const ErrorInfo & e)
         : err(e)
     { }
 
diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc
index 35f7ee917cd3d3be228680f2836e9e5e82afd76c..c8b71188fe0f82e3fe83efa44c02032aaa790218 100644
--- a/src/libutil/serialise.cc
+++ b/src/libutil/serialise.cc
@@ -52,10 +52,10 @@ size_t threshold = 256 * 1024 * 1024;
 
 static void warnLargeDump()
 {
-    logWarning(ErrorInfo {
+    logWarning({
         .name = "Large path",
         .description = "dumping very large path (> 256 MiB); this may run out of memory"
-        });
+    });
 }
 
 
diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc
index 591fff99980795a0820ebd744427565c0b9d03b7..da6f005a314485552a7a74439c612e8319b12679 100755
--- a/src/nix-build/nix-build.cc
+++ b/src/nix-build/nix-build.cc
@@ -368,12 +368,11 @@ static void _main(int argc, char * * argv)
                 shell = drv->queryOutPath() + "/bin/bash";
 
             } catch (Error & e) {
-                logWarning(
-                    ErrorInfo {
-                        .name = "bashInteractive",
-                        .hint = hintfmt("%s; will use bash from your environment", 
-                            (e.info().hint ? e.info().hint->str() : ""))
-                    });
+                logWarning({
+                    .name = "bashInteractive",
+                    .hint = hintfmt("%s; will use bash from your environment",
+                        (e.info().hint ? e.info().hint->str() : ""))
+                });
                 shell = "bash";
             }
         }
diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc
index fdf94e5a37d19b1121b70b69da624c17f0c1b95a..a880bdae097fd7e6b5223ccd003a820103a1335d 100644
--- a/src/nix/upgrade-nix.cc
+++ b/src/nix/upgrade-nix.cc
@@ -68,10 +68,9 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
 
         if (dryRun) {
             stopProgressBar();
-            logWarning(
-                ErrorInfo { 
-                    .name = "Version update",
-                    .hint = hintfmt("would upgrade to version %s", version)
+            logWarning({
+                .name = "Version update",
+                .hint = hintfmt("would upgrade to version %s", version)
             });
             return;
         }