internal/filetypes: better error message for files without extension

Closes #312

Change-Id: I7d7b236e4a90547dcfc0dde94d3a21e7873178d7
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5322
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/testdata/script/issue312.txt b/cmd/cue/cmd/testdata/script/issue312.txt
new file mode 100644
index 0000000..09a227c
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/issue312.txt
@@ -0,0 +1,5 @@
+! cue export -out x.cue
+cmp stderr expect-stderr
+
+-- expect-stderr --
+no encoding specified for file "ut"
diff --git a/internal/filetypes/filetypes.go b/internal/filetypes/filetypes.go
index cad838c..c265070 100644
--- a/internal/filetypes/filetypes.go
+++ b/internal/filetypes/filetypes.go
@@ -192,8 +192,13 @@
 func toFile(i, v cue.Value, filename string) (*build.File, error) {
 	v = v.Fill(filename, "filename")
 	if s, _ := v.Lookup("encoding").String(); s == "" {
-		if len(filename) > 1 { // omit "" and -
-			v = v.Unify(i.Lookup("extensions", filepath.Ext(filename)))
+		if filename != "-" {
+			ext := filepath.Ext(filename)
+			if ext == "" {
+				return nil, errors.Newf(token.NoPos,
+					"no encoding specified for file %q", filename)
+			}
+			v = v.Unify(i.Lookup("extensions", ext))
 		} else {
 			v = v.Unify(i.LookupDef("Default"))
 		}