From 77e625fc9b466a4ee5edcd7c08a7a40e7614ed68 Mon Sep 17 00:00:00 2001 From: lamelizard Date: Tue, 19 Nov 2024 15:58:17 +0100 Subject: [PATCH 1/4] Convenience Function --- .../monticore/types3/util/MapBasedTypeCheck3.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/monticore-grammar/src/main/java/de/monticore/types3/util/MapBasedTypeCheck3.java b/monticore-grammar/src/main/java/de/monticore/types3/util/MapBasedTypeCheck3.java index 68a3091fc..2a0dcd063 100644 --- a/monticore-grammar/src/main/java/de/monticore/types3/util/MapBasedTypeCheck3.java +++ b/monticore-grammar/src/main/java/de/monticore/types3/util/MapBasedTypeCheck3.java @@ -58,6 +58,19 @@ public MapBasedTypeCheck3( this.ctx4Ast = Log.errorIfNull(ctx4Ast); } + /** + * This constructor may only be used + * if the language does not support generics! + * Otherwise, use + * {@link #MapBasedTypeCheck3(ITraverser, Type4Ast, InferenceContext4Ast)}. + */ + public MapBasedTypeCheck3( + ITraverser typeTraverser, + Type4Ast type4Ast + ) { + this(typeTraverser, type4Ast, new InferenceContext4Ast()); + } + /** * This will be set as the TypeCheck3 delegate. */ From be9909fe68588d3fca4e8882f12a921082aeee4e Mon Sep 17 00:00:00 2001 From: lamelizard Date: Tue, 19 Nov 2024 15:58:52 +0100 Subject: [PATCH 2/4] TypeCheck3 Docu Update --- .../java/de/monticore/types3/TypeSystem3.md | 122 ++++++--- .../de/monticore/types3/generics/Generics.md | 235 ++++++++++++++++++ 2 files changed, 327 insertions(+), 30 deletions(-) create mode 100644 monticore-grammar/src/main/java/de/monticore/types3/generics/Generics.md diff --git a/monticore-grammar/src/main/java/de/monticore/types3/TypeSystem3.md b/monticore-grammar/src/main/java/de/monticore/types3/TypeSystem3.md index 64f48e34e..4d30c373f 100644 --- a/monticore-grammar/src/main/java/de/monticore/types3/TypeSystem3.md +++ b/monticore-grammar/src/main/java/de/monticore/types3/TypeSystem3.md @@ -5,23 +5,27 @@ A type system is as set of rules that assign types to terms, e.g., the type `int` can be assigned to the literal `2`. In Monticore, the type system implementations assign SymTypeExpressions to -expressions (e.g., `2`) and type identifiers (e.g., `int`). +expressions (e.g., `2`) and types (e.g., `int`). This is made possible first and foremost by traversing the AST -of the expressions and type identifiers, +of the expression or type, calculating the SymTypeExpressions of its subnodes, and combining their information to the SymTypeExpression currently calculated. ## Given infrastructure in MontiCore -* [Type4Ast](Type4Ast.java) - (maps ASTNodes to SymTypeExpressions, filled by the TypeVisitors) +* [TypeCheck3](TypeCheck3.java) + (offers `typeOf`, etc., to query the SymtypeExpressions of AST nodes.) + * [MapBasedTypeCheck3](util/MapBasedTypeCheck3.java) + (default implementation of TypeCheck3) + * [Type4Ast](Type4Ast.java) + (maps ASTNodes to SymTypeExpressions, filled by the TypeVisitors) * [SymTypeExpression](../types/check/SymTypeExpression.java) (calculated by the TypeVisitors, represents types and "pseudo-types") * [ISymTypeVisitor](ISymTypeVisitor.java) (interface for traversal of SymTypeExpressions) * [SymTypeArray](../types/check/SymTypeArray.java) (subclass of SymTypeExpression, represents arrays, - e.g., `int[2]`) + e.g., `int[]`) * [SymTypeObscure](../types/check/SymTypeObscure.java) (subclass of SymTypeExpression, pseudo-type representing typing errors) * [SymTypeOfFunction](../types/check/SymTypeOfFunction.java) @@ -82,6 +86,21 @@ and combining their information to the SymTypeExpression currently calculated. * [LambdaExpressionsTypeVisitor](../expressions/lambdaexpressions/types3/LambdaExpressionsTypeVisitor.java) (calculates the SymTypeExpressions for the expressions in the grammar LambdaExpressions) + * [OCLExpressionsTypeVisitor](../ocl/oclexpressions/types3/OCLExpressionsTypeVisitor.java) + (calculates the SymTypeExpressions for the expressions + in the grammar OCLExpressions) + * [OptionalOperatorsTypeVisitor](../ocl/optionaloperators/types3/OptionalOperatorsTypeVisitor.java) + (calculates the SymTypeExpressions for the expressions + in the grammar OptionalOperators) + * [SetExpressionsTypeVisitor](../ocl/setexpressions/types3/SetExpressionsTypeVisitor.java) + (calculates the SymTypeExpressions for the expressions + in the grammar SetExpressions) + * [TupleExpressionsTypeVisitor](../expressions/tupleexpressions/types3/TupleExpressionsTypeVisitor.java) + (calculates the SymTypeExpressions for the expressions + in the grammar TupleExpressions) + * [UglyExpressionsTypeVisitor](../expressions/uglyexpressions/types3/UglyExpressionsTypeVisitor.java) + (calculates the SymTypeExpressions for the expressions + in the grammar UglyExpressions) * Literals * [MCCommonLiteralsTypeVisitor](../literals/mccommonliterals/types3/MCCommonLiteralsTypeVisitor.java) (calculates the SymTypeExpressions for the literals @@ -89,25 +108,38 @@ and combining their information to the SymTypeExpression currently calculated. * [MCJavaLiteralsTypeVisitor](../literals/mcjavaliterals/types3/MCJavaLiteralsTypeVisitor.java) (calculates the SymTypeExpressions for the literals in the grammar MCJavaLiterals) - * Type Identifiers + * [SIUnitLiteralsTypeVisitor](../siunit/siunitliterals/types3/SIUnitLiteralsTypeVisitor.java) + (calculates the SymTypeExpressions for the literals + in the grammar SIUnitLiterals) + * Types * [MCArrayTypesTypeVisitor](../types/mcarraytypes/types3/MCArrayTypesTypeVisitor.java) - (calculates the SymTypeExpressions for the type identifiers + (calculates the SymTypeExpressions for the types in the grammar MCArrayTypes) * [MCBasicTypesTypeVisitor](../types/mcbasictypes/types3/MCBasicTypesTypeVisitor.java) - (calculates the SymTypeExpressions for the type identifiers + (calculates the SymTypeExpressions for the types in the grammar MCBasicTypes) * [MCCollectionTypesTypeVisitor](../types/mccollectiontypes/types3/MCCollectionTypesTypeVisitor.java) - (calculates the SymTypeExpressions for the type identifiers + (calculates the SymTypeExpressions for the types in the grammar MCCollectionTypes) * [MCFullGenericTypeVisitor](../types/mcfullgenerictypes/types3/MCFullGenericTypesTypeVisitor.java) - (calculates the SymTypeExpressions for the type identifiers + (calculates the SymTypeExpressions for the types in the grammar MCFullGenericTypes) * [MCFunctionTypesTypeVisitor](../types/mcfunctiontypes/types3/MCFunctionTypesTypeVisitor.java) - (calculates the SymTypeExpressions for the type identifiers + (calculates the SymTypeExpressions for the types in the grammar MCFunctionTypes) * [MCSimpleGenericTypesTypeVisitor](../types/mcsimplegenerictypes/types3/MCSimpleGenericTypesTypeVisitor.java) - (calculates the SymTypeExpressions for the type identifiers + (calculates the SymTypeExpressions for the types in the grammar MCArrayTypes) + * [RegExTypeTypeVisitor](../regex/regextype/types3/RegExTypeTypeVisitor.java) + (calculates the SymTypeExpressions for the types + in the grammar RegExType) + * [SIUnitTypes4ComputingTypeVisitor](../siunit/siunittypes4computing/types3/SIUnitTypes4ComputingTypeVisitor.java) + (calculates the SymTypeExpressions for the types + in the grammar SIUnitTypes4Computing) + * [SIUnitTypes4MathTypeVisitor](../siunit/siunittypes4math/types3/SIUnitTypes4MathTypeVisitor.java) + (calculates the SymTypeExpressions for the types + in the grammar SIUnitTypes4Math) +* Generics infrastructure is [documented separately](./generics/Generics.md#given-infrastructure-in-monticore-wrt-type-inference)! * [TypeCheck1 Adapters](../types/check/types3wrapper/TypeCheck3AsTypeCalculator.java) (adapts the TypeSystem3 to the deprecated TypeCheck1 interface, offering implementations for IDerive and ISynthesize, @@ -115,7 +147,7 @@ and combining their information to the SymTypeExpression currently calculated. ## What is the difference between BasicSymbols and SymTypeExpressions? -The Type System uses the Symbols of the BasicSymbols grammar +The type system uses the Symbols of the BasicSymbols grammar and the handwritten SymTypeExpressions. While they are very similar, there is a big difference between them and when to use them. @@ -167,8 +199,8 @@ offer the following functionalities: * Given an expression, the type of the expression is deduced (e.g., given expression `2+2`, a SymTypeExpression for `int` is created) -* Given a type identifier, - the SymTypeExpression of the identifier is constructed +* Given a type, + the SymTypeExpression of this type is constructed (e.g., given MCType `int` in the model, a corresponding SymTypeExpression is created) * Given one or more types, a relation is checked @@ -189,27 +221,57 @@ This is described in detail further below. Types can be calculated for ASTNodes representing either expressions (`2+2`) -or type identifiers (`String`). +or types (`String`). +This functionality is offered by the class TypeCheck3, +which uses a static delegate pattern; +This static delegate needs to be initialized; +The default (and currently only) implementation is MapBasedTypeCheck3. + First, a Type4Ast map has to be constructed to store the typing information, thus avoiding recalculation if they are queried again, -e.g., by different CoCos. -One may assume that one could store -Afterward creating the map, -a traverser is created with the TypeVisitors of the language, -the TypeVisitors are given the Type4Ast instance. +e.g., by different CoCos. +After creating the map, +a traverser is created with the TypeVisitors of the language components; +The TypeVisitors are given the Type4Ast instance. **Note:** Multiple type visitors, which contain different typing rules, may be available for a given sub-grammar, the visitor to select is to be specified by the language. +In the end, a MapBasedTypeCheck3 has to be created +and set as the delegate of TypeCheck3. + +Example: +```java +// traverser of your language +// no inheritance traverser is used, as it is recommended +// to create a new traverser for each language. +MyLangTraverser traverser = MyLang.traverser(); +// map to store the results +Type4Ast type4Ast = new Type4Ast(); + +// one of many type visitors +// check their documentation, whether further configuration is required +BitExpressionsTypeVisitor visBitExpressions = new BitExpressionsTypeVisitor(); +visBitExpressions.setType4Ast(type4Ast); +traverser.add4BitExpressions(visBitExpressions); + +// create the TypeCheck3 delegate +new MapBasedTypeCheck3(traverser, type4Ast) + .setThisAsDelegate(); +``` An example of instantiating a traverser can be found -[here](../../../../../test/java/de/monticore/types3/util/CombineExpressionsWithLiteralsTypeTraverserFactory.java). -Use the traverser to traverses the given AST and -it stores the calculated SymTypeExpressions in the map. -Finally, the map can be queried for the ASTNode in question. +[here](https://github.com/MontiCore/ocl/blob/dev/src/main/java/de/monticore/ocl/ocl/types3/OCLTypeCheck3.java). +It is recommended to initialize the TypeCheck3 directly after the Mill. + +After initializing the TypeCheck3 delegate, +TypeCheck3 can be used to query SymTypeExpressions of expressions +`TypeCheck3.typeOf(expr)`, +as well as MCTypes +`TypeCheck3.symTypeFromAST(mcType)`. -As an alternativ to using the traverser and map directly, -the TypeCheck1 adapters can be used, -they can be created using the traverser and Type4Ast map. +Note: If the language supports generics, +[additional steps](generics/Generics.md#how-to-get-the-type-of-an-astnode-with-generics) +have to be taken. ### How to check relations on types? @@ -233,13 +295,13 @@ class, but also its subclasses, as they can offer further functionality like, e.g.: `boolean isList(SymTypeExpression type)` -(whether the type is considered a list) +(whether the type is considered a list). As different languages have different typing rules, the corresponding set of rules has to be selected. While this is partially done by selecting the TypeVisitors, relations between types are unrelated to the TypeVisitors -and have to be initialised accordingly. +and have to be initialized accordingly. As an example, the default type relations are initialized using `SymTypeRelations.init()`. diff --git a/monticore-grammar/src/main/java/de/monticore/types3/generics/Generics.md b/monticore-grammar/src/main/java/de/monticore/types3/generics/Generics.md new file mode 100644 index 000000000..98a2de023 --- /dev/null +++ b/monticore-grammar/src/main/java/de/monticore/types3/generics/Generics.md @@ -0,0 +1,235 @@ + + + + +This is an extension of the +[TypeSystem3 documentation](../TypeSystem3.md) +focusing on the support of generics. + +A generic type is a type which contains type parameters. +For example, `List` is a generic type with the name `List` +and one type parameter `T`. +A generic type cannot be used in a model directly! +Instead, it needs to be instantiated by providing type arguments. +`List` is an instantiation of the generic type `List`, +and as such can be used in a model as, e.g., the type of a variable. +In other words, generic types are type-level functions, +that map a non-empty list of types to a new type. + +For MCTypes, the type arguments have to be provided explicitly, +as with `List`. +That is not the case for expressions; +`[]` is an expression that returns an empty `List`. +The type argument is implicitly inferred by using information +of the context the expression is used in. +An Example: + +``` +List persons = []; +List cars = []; +``` + +For `persons` a `List` is expected. +`List` is the _target type_ of the expression `[]`. +Therefore, (in languages that have side effects) the type argument +must be `Person`, thus resulting in the type `List` for `[]`. +The same goes for `cars`; Here, the type argument is required to be `Car`. +As can be seen, the same expression can have different types +depending on the context the expression is used in. + +The implicit type arguments are inferred for + +* checking the type-correctness of the expression +* providing additional information for potential CoCos +* providing additional information for code generators + +To this end, MontiCore provides a type inference algorithm. + +## Given infrastructure in MontiCore wrt. Type Inference + +* [TypeParameterRelations](TypeParameterRelations.java) + (relations over SymTypeExpressions wrt. generics, e.g., hasWildcards) +* [Constraint](constraints/Constraint.java) + (statements over SymTypeExpression that have to hold + for inference to succeed. Leads to Bounds.) + * [SubTypingConstraint](constraints/SubTypingConstraint.java) + (e.g., ``: one SymTypeExpression needs to be + the subtype of another SymTypeExpression) + * [TypeEqualityConstraint](constraints/TypeEqualityConstraint.java) + (e.g., ` = List>`: two SymTypeExpression need to be + the same) + * [TypeCompatibilityConstraint](constraints/TypeCompatibilityConstraint.java) + (e.g., ` FV#0>`: one SymTypeExpression needs to be compatible + to another SymTypeExpression) + * [ExpressionCompatibilityConstraint](constraints/ExpressionCompatibilityConstraint.java) + (e.g., ` float>`: the SymTypeExpression of an expression + needs to be compatible to another SymTypeExpression) + * [BoundWrapperConstraint](constraints/BoundWrapperConstraint.java) + (e.g., ``: a Bound in place of a Constraint) +* [Bound](bounds/Bound.java) + (limits the range of inference variables, intermediate result of inference) + * [SubTypingBound](bounds/SubTypingBound.java) + (e.g., `FV#0 <: Person`: represents a variable to be + a subtype/supertype of a SymTypeExpression) + * [TypeEqualityBound](bounds/TypeEqualityBound.java) + (e.g., `FV#0 = int`: represents a variable being a SymTypeExpression) + * [CaptureBound](bounds/CaptureBound.java) + (e.g., `List = capture(List)`: represents that + capture conversion needs to be done later) + * [UnsatisfiableBound](bounds/UnsatisfiableBound.java) + (`unsatisfiable`: represents that no instantiation can be found) +* Bounds and Constraints: + * [ConstraintReduction](util/ConstraintReduction.java) + (takes Constraints and reduces them to Bounds) + * [BoundIncorporation](util/BoundIncorporation.java) + (takes Bounds and finds new Constraints) + * [BoundResolution](util/BoundResolution.java) + (takes Bounds and resolves instantiations) +* [InferenceContext4Ast](context/InferenceContext4Ast.java) + (maps ASTNodes to SymTypeExpressions, filled by the TypeVisitors) + * [InferenceContext](context/InferenceContext.java) + (stores information required for inference for one ASTNode) + * [InferenceResult](context/InferenceResult.java) + (stores partial results of inference) + * [InferenceVisitorMode](context/InferenceVisitorMode.java) + (the mode the type visitor is in, + this changes the expected behavior wrt. inference) +* [CompileTimeTypeCalculator](util/CompileTimeTypeCalculator.java) + (handles type inference for most visitors. Requires the inference problem + to be representable as a function call.) +* CTTIVisitors are TypeVisitors extended with type inference, + they only exist for expressions + * [AssignmentExpressionsCTTIVisitor](../../expressions/assignmentexpressions/types3/AssignmentExpressionsCTTIVisitor.java) + (calculates the SymTypeExpressions for the expressions + in the grammar AssignmentExpressions) + * [CommonExpressionsCTTIVisitor](../../expressions/commonexpressions/types3/CommonExpressionsCTTIVisitor.java) + (calculates the SymTypeExpressions for the expressions + in the grammar CommonExpressions) + * [ExpressionsBasisCTTIVisitor](../../expressions/expressionsbasis/types3/ExpressionBasisCTTIVisitor.java) + (calculates the SymTypeExpressions for the expressions + in the grammar ExpressionBasis) + * [SetExpressionsCTTIVisitor](../../ocl/setexpressions/types3/SetExpressionsCTTIVisitor.java) + (calculates the SymTypeExpressions for the expressions + in the grammar SetExpressions) + * [UglyExpressionsCTTIVisitor](../../expressions/uglyexpressions/types3/UglyExpressionsCTTIVisitor.java) + (calculates the SymTypeExpressions for the expressions + in the grammar UglyExpressions) + +## Extended SymTypeExpression World + +When adding generics support, one can encounter new SymTypeExpressions; +First of all, there is +[SymTypeOfGenerics](../../types/check/SymTypeOfGenerics.java), +which directly corresponds to +[SymTypeOfObject](../../types/check/SymTypeOfObject.java) +and represents an object type with type arguments, +e.g., `List` (s. above), + +[SymTypeOfFunction](../../types/check/SymTypeOfFunction.java) +does not have a corresponding, e.g., SymTypeOfGenericFunction; +Instead, type arguments are calculated by comparing the +SymTypeOfFunction with the function defined by the FunctionSymbol. +S. `SymtypeOfFunction::getTypeArguments()`. + +There are further types that can be encountered. +Types printed with a `#` are types that are used internally during +type calculations but cannot be explicitly used in a model. +As such, a modeler may only ever encounter them in error messages. + +`"FV#{number}"` (and `CAP#{number}`, etc.) represent inference variables +(free type variables). +They are used in place of the actual type arguments, +until their instantiations are calculated using bounds. + +`#TOP` (commonly written as ⊤) represents the top type, +the type that is the supertype of all types. +It is used internally to represent that there is no upper bound +that limits the set of types an inference variable can be instantiated to. +Example: ` T f()` here, the type variable `T` is has no upper bound +and a corresponding inference variable would use `#TOP` to represent this. + +Inference variables _can_ be instantiated to `#TOP` in specific circumstances; +The return type of `f` in the statement `f();` has no bounds, +it can be any type. As such, `#TOP` is used to represent this. +More often than not, a type of `#TOP` suggests that a type/function +has not been used "to their full potential": +* some information goes unused (for `f` it is the return value), or +* e.g., in the comparison of an empty List and Set `[] == {}` + the potential to store values in the collections goes unused. + +`#BOTTOM` (commonly written as ⊥) represents the bottom type, +the type that is the subtype of all types. +Analogue to `#TOP`, `#BOTTOM` represents +the lack of a more specific lower bound. +`#Bottom` has no values. +Inference variables are never instantiated to `#BOTTOM`. + +### How to get the type of an ASTNode with generics? + +Note: This is an extension of the +[general documentation](../TypeSystem3.md#how-to-get-the-type-of-an-astnode), +which you should read first. + +When calculating types in a language with support for generics, +additional steps have to be taken, due to the inference algorithm + +* using different visitors (not necessarely, but that is usually the case) +* needing to store additional information for ASTNodes, +* and requiring access to the target types of expressions, + +The additional information will be stored in the +[InferenceContext4Ast](context/InferenceContext4Ast.java) +that is shared between all visitors. + +The visitors supporting type inference, so far they exist, +are usually called CTTIVisitors, +for "(extended) **c**ompile-**t**ime **t**ype **i**nference". + +Example: +```java +MyLangTraverser traverser = MyLang.traverser(); +Type4Ast type4Ast = new Type4Ast(); +InferenceContext4Ast ctx4Ast = new InferenceContext4Ast(); + +// one of many type visitors +SetExpressionsCTTIVisitor visSetExpressions = new SetExpressionsCTTIVisitor(); +visSetExpressions.setType4Ast(type4Ast); +visSetExpressions.setContext4Ast(ctx4Ast); +traverser.add4SetExpressions(visSetExpressions); +// due to more complex traversal during type inference, +// most CTTIVisitors need to control the order of traversal +traverser.setSetExpressionsHandler(visSetExpressions); + +// create the TypeCheck3 delegate +new MapBasedTypeCheck3(traverser, type4Ast, ctx4Ast) + .setThisAsDelegate(); +``` + +Again, after initializing the TypeCheck3 delegate, +TypeCheck3 can be used to query SymTypeExpressions of expressions +`TypeCheck3.typeOf(expr)`, +as well as MCTypes +`TypeCheck3.symTypeFromAST(mcType)`. +However, for the expressions, +the target types are required, as far as they exist. +To pass this information to TypeCheck3, +the function `TypeCheck3.typeOf(expr, targetType)` can be used. +This, in addition to calculating the type of `expr`, +stores the target type information; +Any subsequent call to `TypeCheck3.typeOf(expr)` will have the type +according to the target type information stored by the first call. +This data is stored, as there are circumstances there the target type +information is not available (e.g., inside some CoCos). + +It holds that +* Each ASTExpression has exactly one target type +* Each ASTExpression has exactly one type. + In the case of a language with variability, special care has to be taken to + * either reset the value cache accordingly, + * or clone the ASTExpression +* The call to `TypeCheck3.typeOf` *with* the target type has to be the first. + It is recommended to split the post-symbol-table-creation CoCos + into two groups + 1. The group of CoCos that provide the target type information + 2. The group of CoCos that cannot provide the information, + they must run after the CoCos of the first group From 9afa1ad71819c9fbdd9fac00f6241d9fba727e71 Mon Sep 17 00:00:00 2001 From: SE-FDr <88034434+SE-FDr@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:56:45 +0100 Subject: [PATCH 3/4] changed size --- .../src/main/java/de/monticore/types3/generics/Generics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monticore-grammar/src/main/java/de/monticore/types3/generics/Generics.md b/monticore-grammar/src/main/java/de/monticore/types3/generics/Generics.md index 98a2de023..6152334e9 100644 --- a/monticore-grammar/src/main/java/de/monticore/types3/generics/Generics.md +++ b/monticore-grammar/src/main/java/de/monticore/types3/generics/Generics.md @@ -164,7 +164,7 @@ the lack of a more specific lower bound. `#Bottom` has no values. Inference variables are never instantiated to `#BOTTOM`. -### How to get the type of an ASTNode with generics? +## How to get the type of an ASTNode with generics? Note: This is an extension of the [general documentation](../TypeSystem3.md#how-to-get-the-type-of-an-astnode), From 078c50249390457c056ae4cecba05e80944bed47 Mon Sep 17 00:00:00 2001 From: SE-FDr <88034434+SE-FDr@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:21:03 +0100 Subject: [PATCH 4/4] Typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alex Lüpges --- .../src/main/java/de/monticore/types3/generics/Generics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monticore-grammar/src/main/java/de/monticore/types3/generics/Generics.md b/monticore-grammar/src/main/java/de/monticore/types3/generics/Generics.md index 6152334e9..851b522f5 100644 --- a/monticore-grammar/src/main/java/de/monticore/types3/generics/Generics.md +++ b/monticore-grammar/src/main/java/de/monticore/types3/generics/Generics.md @@ -161,7 +161,7 @@ has not been used "to their full potential": the type that is the subtype of all types. Analogue to `#TOP`, `#BOTTOM` represents the lack of a more specific lower bound. -`#Bottom` has no values. +`#BOTTOM` has no values. Inference variables are never instantiated to `#BOTTOM`. ## How to get the type of an ASTNode with generics?