Skip to content

Commit

Permalink
feat: allow literal types as upper bounds of type parameters (#1102)
Browse files Browse the repository at this point in the history
Closes #1081

### Summary of Changes

* Literal types can now be used as upper bounds of type parameters
* Don't show an extra error if callable types or union types are used as
upper bounds of type parameters. This is already checked elsewhere.
  • Loading branch information
lars-reimann authored Apr 25, 2024
1 parent 3021166 commit c14159b
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
import { isStatic, TypeParameter } from '../../../helpers/nodeProperties.js';
import { SafeDsServices } from '../../../safe-ds-module.js';
import { SafeDsNodeMapper } from '../../../helpers/safe-ds-node-mapper.js';
import { NamedType, UnknownType } from '../../../typing/model.js';
import { UnknownType } from '../../../typing/model.js';

export const CODE_TYPE_PARAMETER_INSUFFICIENT_CONTEXT = 'type-parameter/insufficient-context';
export const CODE_TYPE_PARAMETER_UPPER_BOUND = 'type-parameter/upper-bound';
Expand Down Expand Up @@ -66,14 +66,16 @@ export const typeParameterMustHaveSufficientContext = (node: SdsTypeParameter, a
}
};

export const typeParameterUpperBoundMustBeNamedType = (services: SafeDsServices) => {
export const typeParameterUpperBoundMustNotBeUnknown = (services: SafeDsServices) => {
const typeComputer = services.typing.TypeComputer;

return (node: SdsTypeParameter, accept: ValidationAcceptor) => {
const boundType = typeComputer.computeType(node.upperBound);
if (!node.upperBound) {
return;
}

if (boundType !== UnknownType && !(boundType instanceof NamedType)) {
accept('error', 'The upper bound of a type parameter must be a named type.', {
if (typeComputer.computeType(node.upperBound) === UnknownType) {
accept('error', 'The upper bound of a type parameter must not have an unknown type.', {
node,
property: 'upperBound',
code: CODE_TYPE_PARAMETER_UPPER_BOUND,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ import {
typeParameterMustBeUsedInCorrectPosition,
typeParameterMustHaveSufficientContext,
typeParameterMustOnlyBeVariantOnClass,
typeParameterUpperBoundMustBeNamedType,
typeParameterUpperBoundMustNotBeUnknown,
} from './other/declarations/typeParameters.js';
import { callArgumentMustBeConstantIfParameterIsConstant, callMustNotBeRecursive } from './other/expressions/calls.js';
import { divisionDivisorMustNotBeZero } from './other/expressions/infixOperations.js';
Expand Down Expand Up @@ -377,7 +377,7 @@ export const registerValidationChecks = function (services: SafeDsServices) {
typeParameterMustBeUsedInCorrectPosition(services),
typeParameterMustHaveSufficientContext,
typeParameterMustOnlyBeVariantOnClass,
typeParameterUpperBoundMustBeNamedType(services),
typeParameterUpperBoundMustNotBeUnknown(services),
],
SdsTypeParameterList: [
typeParameterListMustNotHaveRequiredTypeParametersAfterOptionalTypeParameters,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package tests.validation.other.declarations.typeParameters.upperBoundMustNotBeUnknown

class C
enum E {
V
}

// $TEST$ no error "The upper bound of a type parameter must not have an unknown type."
class MyClass1<T sub »() -> ()«>

// $TEST$ no error "The upper bound of a type parameter must not have an unknown type."
class MyClass2<T sub »literal<1>«>

// $TEST$ no error "The upper bound of a type parameter must not have an unknown type."
class MyClass3<T sub »C«>

// $TEST$ no error "The upper bound of a type parameter must not have an unknown type."
class MyClass4<T sub »E«>

// $TEST$ no error "The upper bound of a type parameter must not have an unknown type."
class MyClass5<T sub »E.V«>

// $TEST$ no error "The upper bound of a type parameter must not have an unknown type."
class MyClass6<T sub »union<C, E>«>

// $TEST$ error "The upper bound of a type parameter must not have an unknown type."
// $TEST$ no error "The upper bound of a type parameter must not have an unknown type."
class MyClass7<T1 sub »T2«, T2 sub »T1«>

// $TEST$ error "The upper bound of a type parameter must not have an unknown type."
class MyClass8<T sub »Unresolved«>

// $TEST$ error "The upper bound of a type parameter must not have an unknown type."
class MyClass9<T sub »unknown«>

0 comments on commit c14159b

Please sign in to comment.