Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions changelog/dmd.basic-vs-primary-type.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
The term *basic type* is now *primary type*

The parser now uses the term *primary type* for what used to be referred to as *basic type.*
The term *basic type* is used specifically for type expressions that are not immediately recursive.

A *basic type* is a *fundamental type* (those which have keywords)
or a type given by an identifier, a `typeof`, a `mixin`, or a `__traits`.
Absent from this list are `__vector` types and types spelled out using a qualifier and parentheses (e.g. `const(int)`).

A *primary type* is a *basic type* or a `__vector` type or a qualified type.

For the most part, *primary type* is the term you want to use and will see in error messages now.
There are some corners where indeed a *basic type* is required.
18 changes: 18 additions & 0 deletions changelog/dmd.const-base.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Specifying a qualified type as a base class or interface is an error now

A type like `const(Object)` could be used as a base class in the base class list
of a class or interface declaration or of an anonymous class object.
There, qualifiers were simply ignored semantically.

Explicitly qualifying types in base class lists is a parse error now.

This only affects parsing.
If a `mixin` or `typeof` or an identifier is used, nothing changes.
If it resolves to a qualified type,
the qualifier is ignored.
---
class C : const(Object) { } // Parse error now
auto obj = new class const(Object) { }; // Parse error now
---
There is no deprecation period.
The fix is to remove the unnecessary and misleading qualifier from your code.
64 changes: 39 additions & 25 deletions compiler/src/dmd/parse.d
Original file line number Diff line number Diff line change
Expand Up @@ -2813,7 +2813,7 @@
{
case TOK.rightParenthesis:
if (storageClass != 0 || udas !is null)
error("basic type expected, not `)`");
error("primary type expected, not `)`");

Check warning on line 2816 in compiler/src/dmd/parse.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/parse.d#L2816

Added line #L2816 was not covered by tests
break;

case TOK.dotDotDot:
Expand Down Expand Up @@ -3028,7 +3028,7 @@
nextToken();
int alt = 0;
const typeLoc = token.loc;
memtype = parseBasicType();
memtype = parsePrimaryType();
memtype = parseDeclarator(memtype, alt, null);
checkCstyleTypeSyntax(typeLoc, memtype, alt, null);
}
Expand Down Expand Up @@ -3140,7 +3140,7 @@
else
{
Token* t = &token;
if (isBasicType(&t))
if (isPrimaryType(&t))

Check warning on line 3143 in compiler/src/dmd/parse.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/parse.d#L3143

Added line #L3143 was not covered by tests
{
error("named enum cannot declare member with type", (*t).toChars());
nextToken();
Expand Down Expand Up @@ -3541,7 +3541,7 @@
const typeLoc = token.loc;

AST.Type t;
t = parseBasicType();
t = parsePrimaryType();

if (pdeclLoc)
*pdeclLoc = token.loc;
Expand All @@ -3553,7 +3553,7 @@
return t;
}

private AST.Type parseBasicType(bool dontLookDotIdents = false)
private AST.Type parseBasicType(bool dontLookDotIdents = false, bool parsingPrimaryType = false)
{
AST.Type t;
Loc loc;
Expand Down Expand Up @@ -3682,11 +3682,11 @@
{
// ident!(template_arguments)
auto tempinst = new AST.TemplateInstance(loc, id, parseTemplateArguments());
t = parseBasicTypeStartingAt(new AST.TypeInstance(loc, tempinst), dontLookDotIdents);
t = parsePrimaryTypeStartingAt(new AST.TypeInstance(loc, tempinst), dontLookDotIdents);
}
else
{
t = parseBasicTypeStartingAt(new AST.TypeIdentifier(loc, id), dontLookDotIdents);
t = parsePrimaryTypeStartingAt(new AST.TypeIdentifier(loc, id), dontLookDotIdents);
}
break;

Expand All @@ -3702,14 +3702,31 @@

case TOK.dot:
// Leading . as in .foo
t = parseBasicTypeStartingAt(new AST.TypeIdentifier(token.loc, Id.empty), dontLookDotIdents);
t = parsePrimaryTypeStartingAt(new AST.TypeIdentifier(token.loc, Id.empty), dontLookDotIdents);
break;

case TOK.typeof_:
// typeof(expression)
t = parseBasicTypeStartingAt(parseTypeof(), dontLookDotIdents);
t = parsePrimaryTypeStartingAt(parseTypeof(), dontLookDotIdents);
break;

default:
immutable char* kind = parsingPrimaryType ? "primary" : "basic";
error("%s type expected, not `%s`", kind, token.toChars());
if (token.value == TOK.else_)
eSink.errorSupplemental(token.loc, "There's no `static else`, use `else` instead.");
t = AST.Type.terror;
break;
}
return t;
}

private AST.Type parsePrimaryType(bool dontLookDotIdents = false)
{
AST.Type t;
//printf("parsePrimaryType()\n");
switch (token.value)
{
case TOK.vector:
t = parseVector();
break;
Expand Down Expand Up @@ -3757,20 +3774,17 @@
break;

default:
error("basic type expected, not `%s`", token.toChars());
if (token.value == TOK.else_)
eSink.errorSupplemental(token.loc, "There's no `static else`, use `else` instead.");
t = AST.Type.terror;
t = parseBasicType(dontLookDotIdents, /+parsingPrimaryType:+/true);
break;
}
return t;
}

private AST.Type parseBasicTypeStartingAt(AST.TypeQualified tid, bool dontLookDotIdents)
private AST.Type parsePrimaryTypeStartingAt(AST.TypeQualified tid, bool dontLookDotIdents)
{
AST.Type maybeArray = null;
// See https://issues.dlang.org/show_bug.cgi?id=1215
// A basic type can look like MyType (typical case), but also:
// A primary type can look like MyType (typical case), but also:
// MyType.T -> A type
// MyType[expr] -> Either a static array of MyType or a type (iif MyType is a Ttuple)
// MyType[expr].T -> A type.
Expand Down Expand Up @@ -4491,7 +4505,7 @@
}
else
{
ts = parseBasicType();
ts = parsePrimaryType();
ts = parseTypeSuffixes(ts);
}
}
Expand Down Expand Up @@ -4947,7 +4961,7 @@
if (udas)
error("user-defined attributes not allowed for `alias` declarations");

auto t = parseBasicType();
auto t = parsePrimaryType();
t = parseTypeSuffixes(t);
if (token.value == TOK.identifier)
{
Expand Down Expand Up @@ -5092,7 +5106,7 @@
{
// function type (parameters) { statements... }
// delegate type (parameters) { statements... }
tret = parseBasicType();
tret = parsePrimaryType();
tret = parseTypeSuffixes(tret); // function return type
}

Expand Down Expand Up @@ -7201,7 +7215,7 @@
break;
}

if (!isBasicType(&t))
if (!isPrimaryType(&t))
{
goto Lisnot;
}
Expand Down Expand Up @@ -7230,10 +7244,10 @@
return false;
}

// pt = test token. If found, pt is set to the token after BasicType
private bool isBasicType(Token** pt)
// pt = test token. If found, pt is set to the token after PrimaryType
private bool isPrimaryType(Token** pt)
{
// This code parallels parseBasicType()
// This code parallels parsePrimaryType()
Token* t = *pt;
switch (t.value)
{
Expand Down Expand Up @@ -7736,7 +7750,7 @@

default:
{
if (!isBasicType(&t))
if (!isPrimaryType(&t))
return false;
L2:
int tmp = false;
Expand Down Expand Up @@ -8775,7 +8789,7 @@
{
StorageClass stc = parseTypeCtor();

AST.Type t = parseBasicType();
AST.Type t = parsePrimaryType();
t = t.addSTC(stc);

if (stc == 0 && token.value == TOK.dot)
Expand Down Expand Up @@ -9543,7 +9557,7 @@
}

const stc = parseTypeCtor();
auto t = parseBasicType(true);
auto t = parsePrimaryType(true);
t = parseTypeSuffixes(t);
t = t.addSTC(stc);
if (t.ty == Taarray)
Expand Down
4 changes: 2 additions & 2 deletions compiler/test/compilable/test1353.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ interface D(X) {}

void fun()
{
class T : typeof(new A), .B, const(C), D!int {}
class T : typeof(new A), .B, C, D!int {}
version(none)
{
class U : int, float, __vector(int[3]) {}
class U : int, float {}
}
}
2 changes: 1 addition & 1 deletion compiler/test/fail_compilation/b20780.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ TEST_OUTPUT:
---
fail_compilation/b20780.d(10): Error: `@identifier` or `@(ArgumentList)` expected, not `@)`
fail_compilation/b20780.d(11): Error: `@identifier` or `@(ArgumentList)` expected, not `@,`
fail_compilation/b20780.d(11): Error: basic type expected, not `,`
fail_compilation/b20780.d(11): Error: primary type expected, not `,`
---
*/

Expand Down
2 changes: 1 addition & 1 deletion compiler/test/fail_compilation/diag19225.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag19225.d(14): Error: basic type expected, not `else`
fail_compilation/diag19225.d(14): Error: primary type expected, not `else`
fail_compilation/diag19225.d(14): There's no `static else`, use `else` instead.
fail_compilation/diag19225.d(14): Error: found `else` without a corresponding `if`, `version` or `debug` statement
fail_compilation/diag19225.d(15): Error: unmatched closing brace
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/fail_compilation/e15876_3.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/e15876_3.d(28): Error: unexpected `(` in declarator
fail_compilation/e15876_3.d(28): Error: basic type expected, not `=`
fail_compilation/e15876_3.d(28): Error: primary type expected, not `=`
fail_compilation/e15876_3.d(29): Error: found `End of File` when expecting `(`
fail_compilation/e15876_3.d(29): Error: found `End of File` instead of statement
fail_compilation/e15876_3.d(29): Error: expression expected, not `End of File`
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/fail_compilation/e15876_5.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/e15876_5.d(17): Error: basic type expected, not `End of File`
fail_compilation/e15876_5.d(17): Error: primary type expected, not `End of File`
fail_compilation/e15876_5.d(17): Error: semicolon expected to close `alias` declaration, not `End of File`
fail_compilation/e15876_5.d(17): Error: matching `}` expected following compound statement, not `End of File`
fail_compilation/e15876_5.d(16): unmatched `{`
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/fail_compilation/enum_member.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/enum_member.d(14): Error: basic type expected, not `for`
fail_compilation/enum_member.d(14): Error: primary type expected, not `for`
fail_compilation/enum_member.d(15): Error: no identifier for declarator `T`
fail_compilation/enum_member.d(15): Error: found `@` when expecting `,`
fail_compilation/enum_member.d(22): Error: found `}` when expecting `identifier`
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/fail_compilation/fail15667.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/imports/a15667.d(16): Error: basic type expected, not `;`
fail_compilation/imports/a15667.d(16): Error: primary type expected, not `;`
fail_compilation/imports/a15667.d(19): Error: declaration expected following attribute, not end of file
---
*/
Expand Down
4 changes: 2 additions & 2 deletions compiler/test/fail_compilation/ice11982.d
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice11982.d(22): Error: basic type expected, not `scope`
fail_compilation/ice11982.d(22): Error: primary type expected, not `scope`
fail_compilation/ice11982.d(22): Error: found `scope` when expecting `;` following expression
fail_compilation/ice11982.d(22): expression: `new _error_`
fail_compilation/ice11982.d(22): Error: basic type expected, not `}`
fail_compilation/ice11982.d(22): Error: primary type expected, not `}`
fail_compilation/ice11982.d(22): Error: missing `{ ... }` for function literal
fail_compilation/ice11982.d(22): Error: C style cast illegal, use `cast(funk)function _error_()
{
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/fail_compilation/ice15127.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice15127.d(17): Error: basic type expected, not `struct`
fail_compilation/ice15127.d(17): Error: primary type expected, not `struct`
fail_compilation/ice15127.d(17): Error: identifier expected for template value parameter
fail_compilation/ice15127.d(17): Error: found `struct` when expecting `)`
fail_compilation/ice15127.d(17): Error: found `ExampleStruct` when expecting `=`
Expand Down
4 changes: 2 additions & 2 deletions compiler/test/fail_compilation/misc_parser_err_cov1.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
REQUIRED_ARGS: -verrors=0
TEST_OUTPUT:
---
fail_compilation/misc_parser_err_cov1.d(29): Error: basic type expected, not `)`
fail_compilation/misc_parser_err_cov1.d(30): Error: basic type expected, not `)`
fail_compilation/misc_parser_err_cov1.d(29): Error: primary type expected, not `)`
fail_compilation/misc_parser_err_cov1.d(30): Error: primary type expected, not `)`
fail_compilation/misc_parser_err_cov1.d(31): Error: `__traits(identifier, args...)` expected
fail_compilation/misc_parser_err_cov1.d(31): Error: semicolon expected following auto declaration, not `o`
fail_compilation/misc_parser_err_cov1.d(31): Error: expression expected, not `)`
Expand Down
12 changes: 12 additions & 0 deletions compiler/test/fail_compilation/qualbaseclass1.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* TEST_OUTPUT:
---
fail_compilation\qualbaseclass1.d(101): Error: basic type expected, not `const`
fail_compilation\qualbaseclass1.d(101): Error: { } expected following `class` declaration
fail_compilation\qualbaseclass1.d(101): Error: variable name expected after type `const(Object)`, not `{`
fail_compilation\qualbaseclass1.d(101): Error: declaration expected, not `{`
---
*/

#line 100

class C : const(Object) { }
15 changes: 15 additions & 0 deletions compiler/test/fail_compilation/qualbaseclass2.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* TEST_OUTPUT:
---
fail_compilation\qualbaseclass2.d(103): Error: basic type expected, not `const`
fail_compilation\qualbaseclass2.d(103): Error: `{ members }` expected for anonymous class
fail_compilation\qualbaseclass2.d(103): Error: semicolon expected following auto declaration, not `const`
fail_compilation/qualbaseclass2.d(103): Error: variable name expected after type `const(Object)`, not `{`
---
*/

#line 100

void test()
{
auto obj = new class () const(Object) { };
}
4 changes: 2 additions & 2 deletions compiler/test/fail_compilation/udaparams.d
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ fail_compilation/udaparams.d(53): Error: semicolon expected to close `alias` dec
fail_compilation/udaparams.d(53): Error: declaration expected, not `1`
fail_compilation/udaparams.d(54): Error: semicolon expected to close `alias` declaration, not `=>`
fail_compilation/udaparams.d(54): Error: declaration expected, not `1`
fail_compilation/udaparams.d(57): Error: basic type expected, not `@`
fail_compilation/udaparams.d(57): Error: primary type expected, not `@`
fail_compilation/udaparams.d(57): Error: identifier expected for template value parameter
fail_compilation/udaparams.d(57): Error: found `@` when expecting `)`
fail_compilation/udaparams.d(57): Error: basic type expected, not `3`
fail_compilation/udaparams.d(57): Error: primary type expected, not `3`
fail_compilation/udaparams.d(57): Error: found `3` when expecting `)`
fail_compilation/udaparams.d(57): Error: semicolon expected following function declaration, not `)`
fail_compilation/udaparams.d(57): Error: variable name expected after type `T`, not `)`
Expand Down