From 3539af599cec58ab201511d7c22f88b4f6aaaaef Mon Sep 17 00:00:00 2001 From: piegames Date: Sat, 24 Aug 2024 22:57:45 +0200 Subject: [PATCH] libexpr/nix2: Completely remove URI literals Change-Id: I8125e88fd5192f3830385b0960827c8a801c95ca --- src/libexpr/parser/grammar2.hh | 45 +++----------------------- src/libexpr/parser/parser-impl2.inc.cc | 12 ------- src/libutil/experimental-features.cc | 1 + tests/unit/libexpr/trivial.cc | 16 +++++++++ 4 files changed, 21 insertions(+), 53 deletions(-) diff --git a/src/libexpr/parser/grammar2.hh b/src/libexpr/parser/grammar2.hh index 51212b75c..20338996d 100644 --- a/src/libexpr/parser/grammar2.hh +++ b/src/libexpr/parser/grammar2.hh @@ -39,17 +39,6 @@ struct id_rest : sor< one<'_', '\'', '-'> > {}; -struct uri_scheme_first : ranges<'a', 'z', 'A', 'Z'> {}; -struct uri_scheme_rest : sor< - ranges<'a', 'z', 'A', 'Z', '0', '9'>, - one<'+', '-', '.'> -> {}; -struct uri_sep : one<':'> {}; -struct uri_rest : sor< - ranges<'a', 'z', 'A', 'Z', '0', '9'>, - one<'%', '/', '?', ':', '@', '&', '=', '+', '$', ',', '-', '_', '.', '!', '~', '*', '\''> -> {}; - } // "tokens". PEGs don't really care about tokens, we merely use them as a convenient @@ -63,15 +52,8 @@ struct _extend_as_path : seq< c::path_sep, sor > {}; -struct _extend_as_uri : seq< - star, - c::uri_sep, - c::uri_rest -> {}; -// keywords might be extended to identifiers, paths, or uris. -// NOTE this assumes that keywords are a-zA-Z only, otherwise uri schemes would never -// match correctly. +// keywords might be extended to identifiers or paths. // NOTE not a simple seq<...> because this would report incorrect positions for // keywords used inside must<> if a prefix of the keyword matches. template @@ -79,8 +61,7 @@ struct _keyword : sor< seq< S, not_at, - not_at<_extend_as_path>, - not_at<_extend_as_uri> + not_at<_extend_as_path> >, failure > {}; @@ -123,8 +104,6 @@ struct _not_at_any_keyword : minus< // identifiers are kind of horrid: // -// - uri_scheme_first ⊂ id_first -// - uri_scheme_first ⊂ uri_scheme_rest ⊂ path // - id_first ⊂ id_rest ∖ { ' } ⊂ path // - id_first ∩ (path ∖ uri_scheme_first) = { _ } // - uri_sep ∉ ⋃ { id_first, id_rest, uri_scheme_first, uri_scheme_rest, path } @@ -132,7 +111,7 @@ struct _not_at_any_keyword : minus< // // and we want, without reading the input more than once, a string that // matches (id_first id_rest*) and is not followed by any number of -// characters such that the extended string matches path or uri rules. +// characters such that the extended string matches path rules. // // since the first character must be either _ or a uri scheme character // we can ignore path-like bits at the beginning. uri_sep cannot appear anywhere @@ -148,14 +127,7 @@ struct _not_at_any_keyword : minus< struct identifier : _not_at_any_keyword< // we don't use (at, ...) matches here because identifiers are // a really hot path and rewinding as needed by at<> isn't entirely free. - sor< - seq< - c::uri_scheme_first, - star>, - not_at<_extend_as_uri> - >, - one<'_'> - >, + c::id_first, star, one<'_', '-'>>>, not_at<_extend_as_path>, star @@ -176,13 +148,6 @@ struct floating : seq< not_at<_extend_as_path> > {}; -struct uri : seq< - c::uri_scheme_first, - star, - c::uri_sep, - plus -> {}; - struct sep : sor< plus>, seq, star>>, @@ -479,7 +444,6 @@ struct _expr { struct string : semantic, seq {}; struct ind_string : semantic, seq {}; struct path : semantic, seq {}; - struct uri : semantic, t::uri {}; struct rec_set : semantic, _attrset {}; struct set : semantic, _attrset<> {}; @@ -499,7 +463,6 @@ struct _expr { string, ind_string, path, - uri, seq, seps, must, seps, must>>, rec_set, set, diff --git a/src/libexpr/parser/parser-impl2.inc.cc b/src/libexpr/parser/parser-impl2.inc.cc index bb4d9702a..8434ccdcc 100644 --- a/src/libexpr/parser/parser-impl2.inc.cc +++ b/src/libexpr/parser/parser-impl2.inc.cc @@ -640,18 +640,6 @@ template<> struct BuildAST : p::maybe_nothing {}; template<> struct BuildAST : p::maybe_nothing {}; template<> struct BuildAST : p::maybe_nothing {}; -template<> struct BuildAST { - static void apply(const auto & in, ExprState & s, State & ps) { - bool URLLiterals = ps.featureSettings.isEnabled(Dep::UrlLiterals); - if (!URLLiterals) - throw ParseError({ - .msg = HintFmt("URL literals are deprecated, allow using them with --extra-deprecated-features=url-literals"), - .pos = ps.positions[ps.at(in)] - }); - s.pushExpr(ps.at(in), in.string()); - } -}; - template<> struct BuildAST : change_head { static void success(const auto & in, BindingsState & b, ExprState & s, State & ps) { // Before inserting new attrs, check for __override and throw an error diff --git a/src/libutil/experimental-features.cc b/src/libutil/experimental-features.cc index 2e856c52d..19bf58a23 100644 --- a/src/libutil/experimental-features.cc +++ b/src/libutil/experimental-features.cc @@ -187,6 +187,7 @@ constexpr std::array xpFeatureDetails Notable changes done compared to the stable Nix language: - Operators cannot be overridden anymore through `__sub` and friends + - URL literals are completely removed from the language. `x:x` is now a function. See also the `url-literals` deprecated feature - Floating point literals must start with a digit, literals like `.3` are forbidden - Removed ancient `let {` syntax. See also the `ancient-let` deprecated feature )", diff --git a/tests/unit/libexpr/trivial.cc b/tests/unit/libexpr/trivial.cc index 1e9ce14a9..a352cb8a8 100644 --- a/tests/unit/libexpr/trivial.cc +++ b/tests/unit/libexpr/trivial.cc @@ -103,6 +103,22 @@ namespace nix { ASSERT_THROW(eval("https://nixos.org"), Error); } + TEST_F(TrivialExpressionTest, smallestLambda) { + ASSERT_THROW(eval("x:x"), Error); + + FeatureSettings mockFeatureSettings; + mockFeatureSettings.set("deprecated-features", "url-literals"); + + auto v = eval("x:x", true, mockFeatureSettings); + ASSERT_THAT(v, IsStringEq("x:x")); + + // With URI literals now fully removed instead of merely throwing an error, + // the value `x:x` now becomes the lambda it should always have been + mockFeatureSettings.set("experimental-features", "nix-lang2"); + v = eval("(x:x) 42", true, mockFeatureSettings); + ASSERT_THAT(v, IsIntEq(42)); + } + TEST_F(TrivialExpressionTest, withFound) { auto v = eval("with { a = 23; }; a"); ASSERT_THAT(v, IsIntEq(23));