diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index a419e63879..7ca1df6de7 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3449,6 +3449,10 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { c.error('cannot cast `string` to `enum`', node.pos) } } + + if c.pref.warn_about_allocs && to_sym.info is ast.Interface { + c.warn_alloc('cast to interface', node.pos) + } node.typname = c.table.sym(node.typ).name return node.typ } diff --git a/vlib/v/checker/errors.v b/vlib/v/checker/errors.v index 4a55504412..35f9673923 100644 --- a/vlib/v/checker/errors.v +++ b/vlib/v/checker/errors.v @@ -32,6 +32,12 @@ fn (mut c Checker) warn(s string, pos token.Pos) { c.warn_or_error(s, pos, allow_warnings) } +fn (mut c Checker) warn_alloc(s string, pos token.Pos) { + if !c.is_builtin_mod && c.mod !in ['strings', 'math', 'math.bits', 'builtin'] { + c.warn('allocation (${s})', pos) + } +} + fn (mut c Checker) error(message string, pos token.Pos) { if (c.pref.translated || c.file.is_translated) && message.starts_with('mismatched types') { // TODO: move this @@ -178,6 +184,8 @@ fn (mut c Checker) trace[T](fbase string, x &T) { } fn (mut c Checker) deprecate(kind string, name string, attrs []ast.Attr, pos token.Pos) { + // println('deprecate kind=${kind} name=${name} attrs=$attrs') + // print_backtrace() mut deprecation_message := '' now := time.now() mut after_time := now @@ -205,6 +213,8 @@ fn (mut c Checker) deprecate(kind string, name string, attrs []ast.Attr, pos tok } else if after_time == now { c.warn(semicolonize('${start_message} has been deprecated', deprecation_message), pos) + // c.warn(semicolonize('${start_message} has been deprecated!11 m=${deprecation_message}', + // deprecation_message), pos) } else { c.note(semicolonize('${start_message} will be deprecated after ${after_time.ymmdd()}, and will become an error after ${error_time.ymmdd()}', deprecation_message), pos) diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index 078b63c059..31ddf2fcf7 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -850,6 +850,9 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { } } } + if node.op == .plus && c.pref.warn_about_allocs { + c.warn_alloc('string concatenation', node.pos) + } /* if (node.left is ast.InfixExpr && node.left.op == .inc) || (node.right is ast.InfixExpr && node.right.op == .inc) { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index eebc54d07c..860e0ad076 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -2564,6 +2564,13 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ if exp_sym.info.is_generic { fname = g.generic_fn_name(exp_sym.info.concrete_types, fname) } + // Do not allocate for `Interface(unsafe{nil})` casts + is_nil_cast := expr is ast.UnsafeExpr && expr.expr is ast.Nil + if is_nil_cast { + g.write('/*nili*/') + g.write('((void*)0)') + return + } g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, got_is_ptr, false, got_styp) } diff --git a/vlib/v/parser/tmpl.v b/vlib/v/parser/tmpl.v index 31b3fb15cb..f3745c906b 100644 --- a/vlib/v/parser/tmpl.v +++ b/vlib/v/parser/tmpl.v @@ -245,7 +245,9 @@ fn vweb_tmpl_${fn_name}() string { // Remove new line byte source.go_back(1) source.writeln(parser.tmpl_str_end) - source.writeln(' } else { ') + pos := line.index('@else') or { continue } + source.writeln('}' + line[pos + 1..] + '{') + // source.writeln(' } else { ') source.writeln(tmpl_str_start) continue } @@ -332,7 +334,7 @@ fn vweb_tmpl_${fn_name}() string { } if pos := line.index('%') { - // %translation_key => ${tr('translation_key')} + // %translation_key => ${tr('translation_key')} mut line_ := line if pos + 1 < line.len && line[pos + 1].is_letter() { //|| line[pos + 1] == '_' { mut end := pos + 1 diff --git a/vlib/v/pref/pref.v b/vlib/v/pref/pref.v index 161712752f..44b3aafff6 100644 --- a/vlib/v/pref/pref.v +++ b/vlib/v/pref/pref.v @@ -232,8 +232,9 @@ pub mut: checker_match_exhaustive_cutoff_limit int = 12 thread_stack_size int = 8388608 // Change with `-thread-stack-size 4194304`. Note: on macos it was 524288, which is too small for more complex programs with many nested callexprs. // wasm settings: - wasm_stack_top int = 1024 + (16 * 1024) // stack size for webassembly backend - wasm_validate bool // validate webassembly code, by calling `wasm-validate` + wasm_stack_top int = 1024 + (16 * 1024) // stack size for webassembly backend + wasm_validate bool // validate webassembly code, by calling `wasm-validate` + warn_about_allocs bool // -warn-about-allocs warngs about every single allocation, e.g. 'hi $name'. Mostly for low level development where manual memory management is used. // temp // use_64_int bool } @@ -504,6 +505,9 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin '-sourcemap' { res.sourcemap = true } + '-warn-about-allocs' { + res.warn_about_allocs = true + } '-sourcemap-src-included' { res.sourcemap_src_included = true } diff --git a/vlib/v/slow_tests/valgrind/nil_interface.v b/vlib/v/slow_tests/valgrind/nil_interface.v new file mode 100644 index 0000000000..8ec5c29f3c --- /dev/null +++ b/vlib/v/slow_tests/valgrind/nil_interface.v @@ -0,0 +1,6 @@ +interface Resource {} + +fn main() { + mut resource := &Resource(unsafe { nil }) + _ = resource +} diff --git a/vlib/veb/oauth/oauth.v b/vlib/veb/oauth/oauth.v new file mode 100644 index 0000000000..114358202f --- /dev/null +++ b/vlib/veb/oauth/oauth.v @@ -0,0 +1,63 @@ +module oauth + +import json +import net.http + +pub enum TokenPostType { + form + json +} + +pub struct Context { + token_url string + client_id string + client_secret string + token_post_type TokenPostType = .form + redirect_uri string +} + +pub struct Request { +pub: + client_id string + client_secret string + code string + state string +} + +pub fn (ctx &Context) get_token(code string) string { + oauth_request := Request{ + client_id: ctx.client_id + client_secret: ctx.client_secret + code: code + // state: csrf + } + + js := json.encode(oauth_request) + if ctx.token_post_type == .json { + resp := http.post_json(ctx.token_url, js) or { + // app.info(err.msg()) + + // return app.redirect_to_index() + return '' + } + println('OAUTH RESPONSE ${resp}') + return resp.body + } else { + resp := http.post_form(ctx.token_url, { + 'client_id': ctx.client_id + 'client_secret': ctx.client_secret + 'code': code + 'grant_type': 'authorization_code' + //'scope': bot + 'redirect_uri': ctx.redirect_uri + }) or { + // app.info(err.msg()) + + // return app.redirect_to_index() + return '' + } + println('OAUTH RESPONSE ${resp}') + return resp.body + } + return '' +} diff --git a/vlib/x/vweb/vweb.v b/vlib/x/vweb/vweb.v index 58fc2468bb..b955a4340c 100644 --- a/vlib/x/vweb/vweb.v +++ b/vlib/x/vweb/vweb.v @@ -1,3 +1,4 @@ +//@[deprecated: '`x.vweb` is now `veb`. The module is no longer experimental.'] module vweb import io