libexpr/nix2: Completely remove URI literals

Change-Id: I8125e88fd5192f3830385b0960827c8a801c95ca
This commit is contained in:
piegames 2024-08-24 22:57:45 +02:00
parent be050e189b
commit 3539af599c
4 changed files with 21 additions and 53 deletions

View file

@ -39,17 +39,6 @@ struct id_rest : sor<
one<'_', '\'', '-'> 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 // "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, c::path_sep,
sor<c::path, TAO_PEGTL_STRING("${")> sor<c::path, TAO_PEGTL_STRING("${")>
> {}; > {};
struct _extend_as_uri : seq<
star<c::uri_scheme_rest>,
c::uri_sep,
c::uri_rest
> {};
// keywords might be extended to identifiers, paths, or uris. // keywords might be extended to identifiers or paths.
// NOTE this assumes that keywords are a-zA-Z only, otherwise uri schemes would never
// match correctly.
// NOTE not a simple seq<...> because this would report incorrect positions for // NOTE not a simple seq<...> because this would report incorrect positions for
// keywords used inside must<> if a prefix of the keyword matches. // keywords used inside must<> if a prefix of the keyword matches.
template<typename S> template<typename S>
@ -79,8 +61,7 @@ struct _keyword : sor<
seq< seq<
S, S,
not_at<c::id_rest>, not_at<c::id_rest>,
not_at<_extend_as_path>, not_at<_extend_as_path>
not_at<_extend_as_uri>
>, >,
failure failure
> {}; > {};
@ -123,8 +104,6 @@ struct _not_at_any_keyword : minus<
// identifiers are kind of horrid: // identifiers are kind of horrid:
// //
// - uri_scheme_first ⊂ id_first
// - uri_scheme_first ⊂ uri_scheme_rest ⊂ path
// - id_first ⊂ id_rest { ' } ⊂ path // - id_first ⊂ id_rest { ' } ⊂ path
// - id_first ∩ (path uri_scheme_first) = { _ } // - id_first ∩ (path uri_scheme_first) = { _ }
// - uri_sep ∉ { id_first, id_rest, uri_scheme_first, uri_scheme_rest, path } // - 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 // 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 // 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 // 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 // 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< struct identifier : _not_at_any_keyword<
// we don't use (at<id_rest>, ...) matches here because identifiers are // we don't use (at<id_rest>, ...) matches here because identifiers are
// a really hot path and rewinding as needed by at<> isn't entirely free. // a really hot path and rewinding as needed by at<> isn't entirely free.
sor< c::id_first,
seq<
c::uri_scheme_first,
star<ranges<'a', 'z', 'A', 'Z', '0', '9', '-'>>,
not_at<_extend_as_uri>
>,
one<'_'>
>,
star<sor<ranges<'a', 'z', 'A', 'Z', '0', '9'>, one<'_', '-'>>>, star<sor<ranges<'a', 'z', 'A', 'Z', '0', '9'>, one<'_', '-'>>>,
not_at<_extend_as_path>, not_at<_extend_as_path>,
star<c::id_rest> star<c::id_rest>
@ -176,13 +148,6 @@ struct floating : seq<
not_at<_extend_as_path> not_at<_extend_as_path>
> {}; > {};
struct uri : seq<
c::uri_scheme_first,
star<c::uri_scheme_rest>,
c::uri_sep,
plus<c::uri_rest>
> {};
struct sep : sor< struct sep : sor<
plus<one<' ', '\t', '\r', '\n'>>, plus<one<' ', '\t', '\r', '\n'>>,
seq<one<'#'>, star<not_one<'\r', '\n'>>>, seq<one<'#'>, star<not_one<'\r', '\n'>>>,
@ -479,7 +444,6 @@ struct _expr {
struct string : semantic, seq<grammar::v2::string> {}; struct string : semantic, seq<grammar::v2::string> {};
struct ind_string : semantic, seq<grammar::v2::ind_string> {}; struct ind_string : semantic, seq<grammar::v2::ind_string> {};
struct path : semantic, seq<grammar::v2::path> {}; struct path : semantic, seq<grammar::v2::path> {};
struct uri : semantic, t::uri {};
struct rec_set : semantic, _attrset<must, t::kw_rec, seps> {}; struct rec_set : semantic, _attrset<must, t::kw_rec, seps> {};
struct set : semantic, _attrset<> {}; struct set : semantic, _attrset<> {};
@ -499,7 +463,6 @@ struct _expr {
string, string,
ind_string, ind_string,
path, path,
uri,
seq<one<'('>, seps, must<expr>, seps, must<one<')'>>>, seq<one<'('>, seps, must<expr>, seps, must<one<')'>>>,
rec_set, rec_set,
set, set,

View file

@ -640,18 +640,6 @@ template<> struct BuildAST<grammar::v2::expr::string> : p::maybe_nothing {};
template<> struct BuildAST<grammar::v2::expr::ind_string> : p::maybe_nothing {}; template<> struct BuildAST<grammar::v2::expr::ind_string> : p::maybe_nothing {};
template<> struct BuildAST<grammar::v2::expr::path> : p::maybe_nothing {}; template<> struct BuildAST<grammar::v2::expr::path> : p::maybe_nothing {};
template<> struct BuildAST<grammar::v2::expr::uri> {
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<ExprString>(ps.at(in), in.string());
}
};
template<> struct BuildAST<grammar::v2::expr::rec_set> : change_head<BindingsState> { template<> struct BuildAST<grammar::v2::expr::rec_set> : change_head<BindingsState> {
static void success(const auto & in, BindingsState & b, ExprState & s, State & ps) { static void success(const auto & in, BindingsState & b, ExprState & s, State & ps) {
// Before inserting new attrs, check for __override and throw an error // Before inserting new attrs, check for __override and throw an error

View file

@ -187,6 +187,7 @@ constexpr std::array<ExperimentalFeatureDetails, numXpFeatures> xpFeatureDetails
Notable changes done compared to the stable Nix language: Notable changes done compared to the stable Nix language:
- Operators cannot be overridden anymore through `__sub` and friends - 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 - Floating point literals must start with a digit, literals like `.3` are forbidden
- Removed ancient `let {` syntax. See also the `ancient-let` deprecated feature - Removed ancient `let {` syntax. See also the `ancient-let` deprecated feature
)", )",

View file

@ -103,6 +103,22 @@ namespace nix {
ASSERT_THROW(eval("https://nixos.org"), Error); 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) { TEST_F(TrivialExpressionTest, withFound) {
auto v = eval("with { a = 23; }; a"); auto v = eval("with { a = 23; }; a");
ASSERT_THAT(v, IsIntEq(23)); ASSERT_THAT(v, IsIntEq(23));